tag:blogger.com,1999:blog-85030454201933359742024-02-19T12:21:24.929+01:00Ollis BlogIch bin Oliver Skibbe, 27 Jahre alt und als System-Administrator, Entwickler und für alles Kreative im IT-Bereich tätig, dazu mache ich meinen Informatik-Betriebswirt im Abendstudium.
Meine Berufserfahrung umfasst eine IT-Ausbildung bei einer Kommunalverwaltung, 3 Jahre bei einem IT-Dienstleister (http://www.ciphron.de) und aktuell als "interner Dienstleister" bei einem Unternehmen aus dem GKV-Bereich tätig.
Dabei begegnen mir die interessante Dinge, über die ich ein wenig berichten werde.Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-8503045420193335974.post-936244916253915152014-10-07T10:10:00.000+02:002014-10-08T10:28:36.786+02:00Ubuntu 12.04: Probleme bei der Nutzung von check_vmware_api.pl / check_vmware_esx<div dir="ltr" style="text-align: left;" trbidi="on">
Wenn es um die Überwachung von ESX-Servern geht, haben sich zwei Plugins bei mir bewährt.<br />
<br />
<ul style="text-align: left;">
<li><a href="http://exchange.nagios.org/directory/Plugins/Operating-Systems/*-Virtual-Environments/VMWare/check_vmware_api/details" target="_blank">check_vmware_api.pl</a> (ehemals check_esx3.pl)</li>
<li><a href="https://exchange.icinga.org/exchange/check_vmware_esx.pl+-+a+fork+of+check_vmware_api.pl+%28check_esx3.pl%29" target="_blank">check_vmware_esx.pl</a> - Fork von check_vmware_api.pl (aktuell meine präferierte Variante)</li>
</ul>
<div>
Auf die Installation des Plugins gehe ich jetzt nicht weiter ein, sondern mehr auf meine Fallstricke/Optimierungen</div>
<div>
<br /></div>
<h3 style="text-align: left;">
1. Nutzung der Umgebungsvariablen http_proxy / https_proxy</h3>
<div>
<br /></div>
<div>
<div>
Falls die Umgebungsvariablen http(s)_proxy gesetzt sind, wird der Abruf der Daten über den Proxyserver erfolgen (falls keine Ausnahmen deklariert wurden), umgehen kann man dieses, indem man die Skripte um folgende Zeilen erweitert:</div>
</div>
<div>
<br /></div>
<div>
Erweiterung der Plugins um folgende Zeilen (z.B. auf Höhe der Variablen-Deklaration)</div>
<br />
<div>
# reset proxy</div>
<div>
<div>
$ENV{http_proxy} = "";</div>
<div>
$ENV{https_proxy} = "";</div>
</div>
<div>
<br /></div>
<div>
Streng genommen würde https_proxy reichen, da die Requests über SSL erfolgen.</div>
<div>
<br /></div>
<h3 style="text-align: left;">
2. Timeouts beim Abruf mit Ubuntu 12.04</h3>
<div>
<br /></div>
<br />
<div>
Da scheinbar das vSphere SDK nicht mit den aktuellen libwww-perl Modulen zurecht kommen, muss eine ältere Version installiert werden:</div>
<div>
<br /></div>
<br />
<div>
cpan[1]> i /libwww-perl/</div>
<div>
<div>
Going to read '/root/.cpan/Metadata'</div>
<div>
Database was generated on Mon, 06 Oct 2014 13:17:02 GMT</div>
<div>
Distribution GAAS/libwww-perl-5.837.tar.gz</div>
<div>
Distribution MSCHILLI/libwww-perl-6.08.tar.gz</div>
<div>
Author LWWWP ("The libwww-perl mailing list" <libwww@perl.org>)</div>
<div>
3 items found</div>
</div>
<div>
<br /></div>
<div>
cpan[2]> install GAAS/libwww-perl-5.837.tar.gz</div>
<div>
<br /></div>
<div>
Anschließend klappt der Abruf der Daten.</div>
<div>
<br /></div>
<h3 style="text-align: left;">
3. Ablegen der Session Files in ein TMPFS</h3>
<div>
<br /></div>
<div>
Um die Performance zu steigern empfiehlt es sich eine RAM-Disk als Plugin Cache anzulegen, dazu erstellt man folgenden Eintrag in der /etc/fstab</div>
<div>
<br /></div>
<div>
<div>
# nagios plugins</div>
<div>
tmpfs /var/cache/nagios_plugin tmpfs nodev,nosuid,noexec,nodiratime,<b>size=512M</b> 0 0</div>
</div>
<div>
<br /></div>
<div>
Der Parameter "size" muss natürlich angepasst werden, möglich sind dort die Kombinationen </div>
<div>
<ul style="text-align: left;">
<li>% - z.B. 10% des zur Verfügung stehenden RAMs</li>
<li>k,m,g - Angabe in Kilobyte,Megabyte oder Gigabyte</li>
</ul>
<div>
<br />
Achtung: wenn die RAM-Disk zu groß angelegt wird, kann es zu Problemen mit dem System kommen, daher vorher mit "free -m" überprüfen.</div>
</div>
<div>
<br /></div>
<div>
Anschließend wird der mount point erstellt und die Zugriffsrechte für den Nagios/Icinga User gesetzt:</div>
<div>
<br /></div>
<div>
$ mkdir /var/cache/nagios_plugin</div>
<div>
$ chown nagios:nagios $_</div>
<div>
<br /></div>
<div>
Kleine Randnotiz: innerhalb der bash enthält die Variable "$_" das letzte Argument des zuletzt ausgeführten Befehls.</div>
<div>
<br /></div>
<div>
Nun soll die RAM-Disk gemountet werden:</div>
<div>
$ mount /var/cache/nagios_plugn</div>
<div>
<br /></div>
<div>
Im Plugin muss nun noch die Variable plugin_cache angepasst werden:</div>
<div>
$ sed -i 's/plugin_cache=.*/plugin_cache="\/var\/cache\/nagios_plugin\/";/g' /usr/lib/nagios/plugins/check_vmware_esx</div>
<div>
<br /></div>
<div>
Dabei muss noch der Pfad des Plugins entsprechend angepasst werden.</div>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-76284388688483007472014-08-28T13:04:00.000+02:002014-08-28T13:04:25.758+02:00Nagios: NetApp Plugin check_netapp_sdk.pl<div dir="ltr" style="text-align: left;" trbidi="on">
<span class="listing-desc">Written in Perl, using NetApp Manageability SDK <br />
</span><br />
<span class="listing-desc"><br /></span>
<span class="listing-desc">Functions</span><br />
<ul style="text-align: left;">
<li><span class="listing-desc">
check-volume</span></li>
<li><span class="listing-desc">
check-lun</span></li>
<li><span class="listing-desc">
check-snapmirror</span></li>
<li><span class="listing-desc">
check-aggr</span></li>
<li><span class="listing-desc">
check-cluster</span></li>
<li><span class="listing-desc">
check-shelf</span></li>
<li><span class="listing-desc">
check-license</span></li>
</ul>
<br />
<div class="listing-fulldesc">
Dependencies:
<br />
- NetApp 7-Mode
<br />
- Nagios::Plugins (Perl)
<br />
- NetApp Manageability SDK (Perl)
<br />
- At line 24 adjust your lib path:
<br />
use lib "/usr/lib/perl5/site_perl/5.8.8/NetApp";
<br />
- Warning/Critical defaults to 85/95%
<br />
<br />
<br />
check-volume [-n VOLUME_NAME] - List volumes use -n to specify volume
<br />
-> size in percent (-w/-c)
<br />
check-lun [-n LUN_NAME] - List LUNs, use -n to specify lun
<br />
-> size in percent (-w/-c)
<br />
-> misalignment results to warning
<br />
-> offline state and is mapped results to critical
<br />
check-snapmirror [-n SNAPMIRROR_NAME] - List snapmirrors, use -n to specify snapmirror
<br />
-> lag_time in seconds (-w/-c)
<br />
-> transfer error -> CRITICAL
<br />
check-aggr [-n AGGREGATE_NAME] - List aggregates, use -n to specify lun
<br />
-> size in percent (-w/-c)
<br />
-> mount state: warning on creating, mounting, unmounting, quiescing;
ok on online consistent quiesced; critical for the rest!
<br />
-> mirror state: warning on 'CP count check in progress'; ok on mirrored, unmirrored; critical for the rest!
<br />
-> raid state: warning on resyncing, copying, growing, reconstruct; ok on normal, mirrored; critical for the rest
<br />
-> inconsistency results on critical
<br />
check-cluster - checks for cluster state
<br />
-> warning/critical on other state than connected
<br />
-> warning on inactive hwassist (if available)
<br />
-> interconnect state
<br />
check-shelf
<br />
-> critical on failed power-supply
<br />
-> critical on failed voltage sensor
<br />
-> critical on failed temp sensor
<br />
-> temperature (values provided by netapp, is needed due to different sensor locations)
<br />
-> shelf state : warning on informational, non_critical; ok on normal; critical for the rest!
<br />
check-license - checks license
<br />
-> expiry date (excludes demo, auto_enabled and non expiry lics)
<br />
<br />
Sample Output:
<br />
<br />
<br />
$ check_netapp_sdk.pl -H snapmirror1 -U $USER1$ -P $USER2$ -S -C check-snapmirror -w 43200 -c 86400<br />
CRITICAL - 1 failed snapmirror found: C->netapp1->snapmirror1:
nfs_ds2_snapmirror: Lag-time: 10.2 days Error: - |
netapp1_snapmirror1_nfs_ds2_snapmirror_xfer_size=36609B;;
netapp1_snapmirror1_nfs_ds2_snapmirror_lag_time=885023s;43200;86400<br />
<br />
$ check_netapp_sdk.pl -H netapp1 -U $USER1$ -P $USER2$ -S -C check-cluster<br />
OK - Cluster is fine! Partner netapp2 is connected<br />
<br />
$ check_netapp_sdk.pl -H netapp1 -U $USER1$ -P $USER2$ -S -C check-lun -n /vol/lun_1_vol/lun_1<br />
WARNING - 1 suspicious luns found: W->lun_1: 85.66% |
lun_1_size_used=44911216B;44564480;47185920;;52428800
lun_1_size_pct=85.66%;85;9<br />
<br />
$ check_netapp_sdk.pl -H netapp1 -U $USER1$ -P $USER2$ -S -C check-volume -n lun_1_vol<br />
WARNING - 1 suspicious volumes found: W->lun_1_vol: 88.56% |
lun_1_vol_size_used=52653680B;50537015;53509781;;59455312
lun_1_vol_size_pct=88.56%;85;9<br />
<br />
$ check_netapp_sdk.pl -H netapp1 -U $USER1$ -P $USER2$ -S -C check-aggr<br />
OK - 0 suspicious aggregate found |
aggr_unmirrored_size_used=3161408134.68B;3274284218;3466889172;;3852099080
aggr_unmirrored_size_pct=82.07%;85;90
aggr0_size_used=10676546580.44B;11114697879;11768503637;;13076115152
aggr0_size_pct=81.65%;85;90<br />
<br />
$ check_netapp_sdk.pl -H netapp1 -U $USER1$ -P $USER2$ -S -C check-license<br />
OK - 0/48 expired licenses found<br />
<br />
$ check_netapp_sdk.pl -H netapp1 -U $USER1$ -P $USER2$ -S -C check-version<br />
OK - System-Name: netapp1 System-ID: 123456789 Model: FAS3240 Serial:
123456789 Version: NetApp Release 8.1.2P4 7-Mode: Fri Apr 26 19:57:25
PDT 2013</div>
<div class="listing-fulldesc">
</div>
<div class="listing-fulldesc">
</div>
<div class="listing-fulldesc">
<a href="http://www.monitoring-portal.org/wbb/index.php?page=Thread&threadID=31551" target="_blank">http://www.monitoring-portal.org/wbb/index.php?page=Thread&threadID=31551</a></div>
<div class="listing-fulldesc">
</div>
<div class="listing-fulldesc">
Download: <a href="http://exchange.nagios.org/directory/Plugins/Hardware/Storage-Systems/SAN-and-NAS/NetApp/check_netapp_sdk-2Epl/details" target="_blank">http://exchange.nagios.org/directory/Plugins/Hardware/Storage-Systems/SAN-and-NAS/NetApp/check_netapp_sdk-2Epl/details</a></div>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com4tag:blogger.com,1999:blog-8503045420193335974.post-62112183086692563622014-08-20T07:26:00.004+02:002014-11-27T13:37:26.496+01:00Nachtrag für Ubuntu 14.04 Trusty zu Active-Directory User-Login für Ubuntu/Debian Servern<div dir="ltr" style="text-align: left;" trbidi="on">
Nachdem ich gestern das erste System von 12.04 auf 14.04 gehoben habe, musste ich feststellen, dass der AD-Login (wie hier beschrieben: <a href="http://oskibbe.blogspot.de/2014/07/linux-active-directory-user-login-fur.html" target="_blank">http://oskibbe.blogspot.de/2014/07/linux-active-directory-user-login-fur.html</a>) nicht mehr funktionierte.<br />
<br />
<br />
Der Server war weiterhin in der Domäne und die Winbind Tools wbinfo -u / wbinfo -g lieferten weiterhin die korrekten User/Gruppen zurück.<br />
<br />
Im Auth-Log fand ich allerdings einen Eintrag:<br />
<br />
<pre>Aug 18 16:07:38 host login[1738]: pam_listfile(login:auth): Refused user oliver.skibbe for service login
Aug 18 16:07:40 host login[1738]: pam_unix(login:auth): check pass; user unknown
Aug 18 16:07:40 host login[1738]: pam_unix(login:auth): authentication failure; logname=LOGIN uid=0 euid=0 tty=/dev/tty1 ruser= rhost=
Aug 18 16:07:40 host login[1738]: pam_winbind(login:auth): getting password (0x00000388)
Aug 18 16:07:40 host login[1738]: pam_winbind(login:auth): pam_get_item returned a password
Aug 18 16:07:42 host login[1738]: FAILED LOGIN (1) on '/dev/tty1' FOR 'UNKNOWN', Authentication failure
</pre>
<div>
Ausgehend von diesem Eintrag und der Info, dass die User weiterhin abrufbar waren, konnte ich das Problem auf nsswitch eingrenzen und zwar gibt es seit Ubuntu 14.04 Trusty für diesen Part zwei zusätzliche Pakete Namens: libnss-winbind und libpam-winbind benötigt werden:<br />
<br />
ii libnss-winbind:amd64 2:4.1.6+dfsg-1ubuntu2.14.04.3 amd64 Samba nameservice integration plugins<br />
ii libpam-winbind:amd64 2:4.1.6+dfsg-1ubuntu2.14.04.3 amd64 Windows domain authentication integration plugin<br />
<div>
<br /></div>
<br />
Nach der Installation dieses Paketes funktionierte dann der AD-Login sofort wieder, schade das Winbind keine explizite Abhängigkeit für dieses Paket hat.</div>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-35248739890506225372014-08-01T10:09:00.002+02:002014-08-01T10:09:46.205+02:00My github for monitoring plugins<div dir="ltr" style="text-align: left;" trbidi="on">
Instead of using a local subversion, i moved my selfwritten monitoring plugins to github.<br />
<br />
It's accessible through this link: <a href="https://github.com/riskersen/Monitoring" target="_blank">https://github.com/riskersen/Monitoring</a><br />
<br />
<br />
Feel free to contribute :-)</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-62467145560870772062014-07-29T10:49:00.002+02:002014-07-29T10:56:05.749+02:00Nagios crashing while using scheduled downtimes, log rotation and MK-Livestatus<div dir="ltr" style="text-align: left;" trbidi="on">
So, this is my first post in English so please don't expect too much ;-)<br />
<br />
<br />
There is a problem in nagios 3.4.x - 3.5.x while using NEB mk_livestatus (<a href="https://mathias-kettner.de/checkmk_livestatus.html" target="_blank">https://mathias-kettner.de/checkmk_livestatus.html</a>), setting <b>log_rotation_method</b> and using scheduled downtimes.<br />
<br />
This bug leads to a crashing nagios process at the time where a logrotate should be done.<br />
<br />
I noticed this after updating nagios core from 3.3.x to 3.4.4 and also in 3.5.1.<br />
<br />
There is a patch available at <a href="http://tracker.nagios.org/view.php?id=455" target="_blank">http://tracker.nagios.org/view.php?id=455</a> (Bug ID 455)<br />
<br />
<pre class="brush:diff;">--- nagios-3.5.0/include/downtime.h 2013-02-10 00:55:47.000000000 +0100
+++ /tmp/downtime.h 2013-04-04 17:05:14.000000000 +0200
@@ -39,24 +39,26 @@
char *service_description;
time_t entry_time;
time_t start_time;
- time_t flex_downtime_start; /* Time the flexible downtime started */
time_t end_time;
int fixed;
unsigned long triggered_by;
unsigned long duration;
unsigned long downtime_id;
- int is_in_effect;
- int start_notification_sent;
char *author;
char *comment;
#ifdef NSCORE
unsigned long comment_id;
+#endif
+ int is_in_effect;
+#ifdef NSCORE
int start_flex_downtime;
int incremented_pending_downtime;
// int start_event;
// int stop_event;
#endif
struct scheduled_downtime_struct *next;
+ time_t flex_downtime_start; /* Time the flexible downtime started */
+ int start_notification_sent;
} scheduled_downtime;
</pre>
This patch also works with 3.5.1 and should be applicable to 3.4.x.<br />
<br />
On my next post i'll talk about creating rpms for nagios (which is very easy if you know how to)<br />
<br />
<br /></div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-80168682311347978122014-07-18T13:46:00.002+02:002014-07-18T13:46:12.705+02:00Linux: Active-Directory User-Login für Ubuntu/Debian Servern<div dir="ltr" style="text-align: left;" trbidi="on">
Warum muss eigentlich für jedes Linux-System immer ein Passwort aus einem Passwort-Manager geholt werden, nur um eben einen Dienst neuzustarten oder die Logs zu durchforsten, wenn wir doch ein funktionierendes Active Directory im Einsatz haben?<br />
<br />
Was muss also her: AD-Login für die Linux-Maschinen (Ubuntu/Debian)!<br />
Da wir aber, wie auf den Windows Servern, nicht jedem den Zugriff und sudo (Kommandos als root ausführen!) erlauben wollen, müssen wir die Zugriffe einschränken, welches ich in diesem kurzen Tutorial ebenfalls tun werde.<br />
<br />
Im Wesentlichen brauchen wir dafür die folgenden Pakete:<br />
<pre>apt-get install winbind samba krb5-user libpam-krb5</pre>
<br />
Winbind übernimmt hier als Komponente von Samba im Zusammenspiel mit PAM & Kerberos die Hauptarbeit.<br />
<br />
<h3 style="text-align: left;">
Kerberos</h3>
Als erstes werden die Kerberos Konfigurationen erledigt, dazu erstellen wir die /etc/krb5.conf in folgender Weise:<br />
<br />
<pre>[libdefaults]
default_realm<span class="Apple-tab-span" style="white-space: pre;"> </span>= DOMAIN.TLD
allow_weak_crypto = yes
# passend zum AD:
default_tkt_enctypes = arcfour-hmac-md5 des-cbc-crc des-cbc-md5
default_tgs_enctypes = arcfour-hmac-md5 des-cbc-crc des-cbc-md5
[domain_realm]
.domain.tld = DOMAIN.TLD
# wir nutzen nicht den PRÄ-2000 Namen!
[realms]
DOMAIN.TLD = {
kdc = dc1.fqdn
kdc = dc2.fqdn
admin_server = dc1.fqdn
}
# wir nutzen nicht den PRÄ-2000 Namen, daher umschreiben, falls nötig
[appdefaults]
pam = {
mappings = DOMAIN_2000\\(.*) $1@DOMAIN.TLD
forwardable = true
validate = true
}
# Vorbereitung für Apache Kerberos Authentifizierung!
httpd = {
mappings = DOMAIN_2000\\(.*) $1@DOMAIN.TLD
reverse_mappings = (.*)@DOMAIN\.TLD DOMAIN_2000\$1
}</pre>
<br />
Zu ändern sind hier nur die Domänen-Namen, also der 2000er Name und die "moderne" Variante, sowie die Domänen-Controller, idealerweise als fqdn.<br />
<br />
Jetzt testen wir den ersten Login mit einem AD-Admin und erzeugen ein Kerberos-Ticket mit<br />
<pre> kinit AD-Admin@DOMAIN.TLD</pre>
<br />
Und lassen uns das erzeugte Ticket anzeigen:<br />
<pre>klist</pre>
<br />
Der Kerberos Part ist damit abgeschlossen.<br />
<h3 style="text-align: left;">
Samba</h3>
<div>
Auch hier müssen wir die Konfiguration in /etc/samba/smb.conf ändern:</div>
<pre>[global]
security = ads
realm = domain.tld
workgroup = DOMAIN
idmap uid = 70000-100000
idmap gid = 70000-100000
winbind enum users = yes
winbind enum groups = yes
winbind use default domain = yes
winbind refresh tickets = yes
template homedir = /home/%U
template shell = /bin/bash
client use spnego = yes
client ntlmv2 auth = yes
encrypt passwords = true
restrict anonymous = 2
domain master = no
local master = no
preferred master = no
os level = 0
socket address = 127.0.0.1
load printers = no
printing = bsd
printcap name = /dev/null
disable spoolss = yes
[domain-share]
path = /foo/bar
comment = Foo-Bar
browseable = no
read only = no
force user = root
force group = "DOMAIN+ad-group"
force create mode = 0666
force directory mode = 2777
force directory security mode = 0777
valid users = @"DOMAIN+ad-group"
</pre>
<br />
Der "domain-share" ist nur ein Beispiel, wie man Samba-Freigaben mit AD Berechtigungen anlegen kann.<br />
Wenn dieser genutzt werden soll, sollte die socket address auf die entsprechende IP-Adresse gesetzt werden oder einfach auskommentiert werden.<br />
Um den Overhead zu reduzieren habe ich dem Samba hier verboten Master zu werden, sowie Druckfunktionen anzubieten.<br />
<br />
Die Konfiguration des Samba ist abgeschlossen, wir müssen nun die smb und winbind (Wichtig!) Dienste neustarten<br />
<pre>/etc/init.d/smbd restart && /etc/init.d/winbind restart</pre>
<div>
<br /></div>
<div>
Fehlt nun noch der AD-Join:<br />
<pre>net ads join -U AD-Admin</pre>
<br />
Ob der AD-Join wirklich erfolgreich war, können wir mit dem Tool wbinfo gut ermitteln:<br />
<pre>wbinfo -u | wc -l</pre>
<br />
wbinfo -u liefert alle User aus dem AD zurück und mit wc -l zählen wir das Ergebnis.<br />
Alternativ geht auch wbinfo -g (Gruppen).<br />
Achtung: es kann eine gewisse Zeit dauern bis wbinfo korrekte Ergebnisse anzeigt!<br />
<br />
Damit wir die gefundenen User auch als User im System und damit auch für die Anmeldung nutzen können, müssen wir am "internen" DNS ebenfalls etwas ändern und zwar in der /etc/nsswitch.conf:<br />
Im Wesentlichen ergänzen wir die Zeilen user und group, so dass diese dann folgendermaßen aussehen:<br />
<pre>passwd: compat winbind
group: compat winbind
</pre>
<br />
Anschließend können wir noch einmal die Dienste neustarten:<br />
<pre>/etc/init.d/smbd restart && /etc/init.d/winbind restart</pre>
<br />
Und einen erneuten Test durchführen, dieses Mal rufen wir die virtuelle passwd inkl. Domänen-User ab:<br />
<pre>getent passwd</pre>
<br />
Hier sollten nun alle Domänen-User im normalen Passwd Format auftauchen:
<br />
<pre>username:*:71776:70000:Surname, givenName:/home/username:/bin/bash</pre>
<br />
Die Domänen-User können wir gut an den IDs über 70000 erkennen.<br />
<br />
Damit haben wir die Samba Konfiguration abgeschlossen.<br />
<br />
<h3 style="text-align: left;">
PAM</h3>
<div>
Dem Plugable Authentication Mechanism, kurz PAM, muss nun noch die Nutzung von Winbind beigebracht werden, dazu wird die Datei /etc/pam.d/common-account um folgende Zeile erweitert:</div>
<pre>account [success=1 new_authtok_reqd=done default=ignore] pam_winbind.so </pre>
<br />
Weiterhin müssen wir Datei /etc/pam.d/common-auth erweitern, so dass sie wie folgt aussieht:<br />
<pre>## restricted access
auth required pam_listfile.so onerr=fail item=group sense=allow file=/etc/login.group.allowed
auth [success=2 default=ignore] pam_unix.so nullok_secure
auth [success=1 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass
# here's the fallback if no module succeeds
auth requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth required pam_permit.so
</pre>
<div>
<br /></div>
<div>
Wir erinnern uns, wir wollen den Zugriff für bestimmte Nutzer Gruppen einschränken, dazu nutzen wir das PAM-Modul pam_listfile.so und tragen dort zeilen-basiert unsere erlaubten Gruppen (ohne Prefix!) ein.<br />
<br />
Damit wir auf jedem System auch ein entsprechendes Home Verzeichnis bekommen, benötigen wir das Modul pam_mkhomedir.so, welches wir in die Datei /etc/pam.d/common-session einfügen:<br />
<pre>session required pam_mkhomedir.so umask=0022 skel=/etc/skel</pre>
<br />
<h3 style="text-align: left;">
Abschluss</h3>
Damit wir die Änderungen testen können, machen wir einen SSH auf uns selbst:<br />
<pre>ssh ad-user@hostname</pre>
<br />
Wenn das erfolgreich ist, fügen wir noch Samba und Winbind zum Autostart hinzu:<br />
<pre>update-rc.d smb defaults && update-rc.d winbind defaults</pre>
<br />
Das wars!<br />
<br />
<h3 style="text-align: left;">
Nachtrag: RHEL/CentOS/Oracle Linux</h3>
Das ganze funktioniert natürlich auch unter RHEL basierten Systen, dafür nutzt man die Pakete:<br />
<pre>nscd pam_krb5 samba-common samba</pre>
<pre>
</pre>
Und ergänzt die Datei /etc/pam.d/system-auth-ac um folgende Zeilen:<br />
<pre>auth sufficient pam_winbind.so use_first_pass</pre>
<pre>account [default=bad success=ok user_unknown=ignore] pam_winbind.so</pre>
<pre>session optional pam_winbind.so mkhomedir</pre>
<br />
Ansonsten variieren natürlich die Befehle etwas.<br />
<br />
<br />
Bei Fragen bitte einfach melden.<br />
<br /></div>
<div>
<br /></div>
<br /></div>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-39428524161828238462014-07-17T09:18:00.000+02:002014-07-17T09:18:01.169+02:00ORA-15303: Probleme beim Erstellen der Voting files für ein Oracle RAC auf RHEL-basierten Linuxen mit iSCSI Luns und ASM<div dir="ltr" style="text-align: left;" trbidi="on">
Es gibt leider einen nervigen Bug(?) bei der Verwendung von Oracle ASM (<a href="http://docs.oracle.com/cd/B28359_01/server.111/b31107/asmcon.htm" target="_blank">http://docs.oracle.com/cd/B28359_01/server.111/b31107/asmcon.htm</a>) im Zusammenspiel mit iSCSI LUNs, der Bug äußert sich bei der Installation einer Grid Infrastructure für Oracle RAC (<a href="http://docs.oracle.com/cd/B28359_01/rac.111/b28254/admcon.htm" target="_blank">http://docs.oracle.com/cd/B28359_01/rac.111/b28254/admcon.htm</a>).<br />
<br />
Man wird nach der X-basierten Installation der Grid Infrastructure gebeten das root.sh Script auszuführen ($ORACLE_HOME/root.sh), dabei kommt es zu einem Fehler, welcher in folgendem Log gefunden werden kann: (eigentlich könnte die Variable imho auch $GRID_HOME genannt werden, aber seis drum):<br />
<br />
$ORACLE_HOME/cfgtoollogs/crsconfig/rootcrs_oraracqs1.log<br />
<br />
2013-10-15 15:29:12: Creating voting files<br />
2013-10-15 15:29:12: Creating voting files in ASM diskgroup OCR_VOTING<br />
2013-10-15 15:29:12: Executing crsctl replace votedisk '+OCR_VOTING'<br />
2013-10-15 15:29:12: Executing /u01/app/11.2.0.3/grid/bin/crsctl replace votedisk '+OCR_VOTING'<br />
2013-10-15 15:29:12: Executing cmd: /u01/app/11.2.0.3/grid/bin/crsctl replace votedisk '+OCR_VOTING'<br />
2013-10-15 15:29:13: Command output:<br />
> Failed to create voting files on disk group OCR_VOTING.<br />
> Change to configuration failed, but was successfully rolled back.<br />
> CRS-4000: Command Replace failed, or completed with errors.<br />
>End Command output<br />
<br />
Diese Ausgabe hilft erstmal nicht wirklich weiter, also schauen wir im ASM Log nach:<br />
<br />
Auf dem 1. Knoten:<br />
/u01/app/grid/diag/asm/+asm/+ASM1/trace/alert_+ASM1.log<br />
<br />
Dort können wir folgende Ausgabe sehen:<br />
NOTE: Voting File refresh pending for group 1/0x4b5bc0ec (OCR_VOTING)<br />
NOTE: Attempting voting file creation in diskgroup OCR_VOTING<br />
ERROR: Could not create voting files. It spans across 161 AUs (max supported is 64 AUs)<br />
ERROR: Voting file allocation failed for group OCR_VOTING<br />
Errors in file /u01/app/grid/diag/asm/+asm/+ASM1/trace/+ASM1_ora_1511.trc:<br />
<b>ORA-15303: Voting files could not be created in diskgroup OCR_VOTING due to small Allocation Unit size</b><br />
NOTE: Attempting voting file refresh on diskgroup OCR_VOTING<br />
<br />
Das hilft uns schon mal etwas weiter, also überprüfen wir die Disks auf ihre Blocksize (hier sdc)<br />
<br />
[root@orarac1 queue]# pwd<br />
/sys/block/sdc/queue<br />
[root@orarac1 queue]# grep "" *block_size<br />
logical_block_size:512<br />
physical_block_size:4096<br />
<br />
Was sehen wir hier? Das SAN präsentiert uns unterschiedliche Werte für die Block Size, um dieses Problem zu beheben müssen wir in der Konfiguration der ASM (/etc/sysconfig/oracleasm) den folgenden Wert von false auf true setzen<br />
<br />
# ORACLEASM_USE_LOGICAL_BLOCK_SIZE: 'true' means use the logical block size<br />
# reported by the underlying disk instead of the physical. The default<br />
# is 'false'<br />
<b>ORACLEASM_USE_LOGICAL_BLOCK_SIZE=true</b><br />
<div>
<br /></div>
<div>
Alternativ kann das auch mittels Konfigurations-Tool gesetzt werden:</div>
<div>
<div>
/usr/sbin/oracleasm configure -b</div>
</div>
<div>
<br /></div>
<div>
Anschließend muss die Konfiguration aktiviert werden:</div>
<div>
service oracleasm restart</div>
<div>
<br /></div>
<div>
Wenn wir nun das root.sh Skript erneut ausführen, funktioniert die Erstellung der Voting Files auf unserer ASM Diskgroup.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Für weitere Informationen empfiehlt sich das Studium des Oracle MetaLinks DOC-ID: 1526096.1</div>
<div>
<br /></div>
<div>
<br /></div>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-44324216624734865962014-07-01T12:01:00.002+02:002014-07-01T12:01:40.918+02:00Wie funktioniert eigentlich der Linux IO-Stack oder wie kommen wir Performance Problemen auf die Schliche<div dir="ltr" style="text-align: left;" trbidi="on">
Bei Performance Problemen ist es immer nett zu wissen, an welchen Stellen man suchen sollte. <br />
<br />
<br />
Dazu bin ich im Thomas-Krenn Wiki auf eine nette Grafik zum Thema IO-Stack unter Linux gestoßen:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN2kd4HOdJEotTLFx5-sxKLRG754WRMqm-OsVnOrAlzfImdY-SdinFST6YZ87h0WDGdk-6Yz6Md0QgfWFOtahl1Syr8jGWxTl_NH8aqF6egNkNDek-JR0og0SAqD-bqi3b6FGeY52ryo1s/s1600/linux-io-stack-diagram_v1.0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Linux I/O Stack Diagram" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN2kd4HOdJEotTLFx5-sxKLRG754WRMqm-OsVnOrAlzfImdY-SdinFST6YZ87h0WDGdk-6Yz6Md0QgfWFOtahl1Syr8jGWxTl_NH8aqF6egNkNDek-JR0og0SAqD-bqi3b6FGeY52ryo1s/s1600/linux-io-stack-diagram_v1.0.png" height="640" title="Linux I/O Stack Diagram" width="452" /></a></div>
<br />
Schön und gut, wir wissen nun wie der IO-Stack arbeitet, aber wie kommen wir nun tatsächlich unserem Performance-Problem auf die Schliche? Dazu gucken wir uns das Diagramm von Brendan Gregg - Linux Performance Analysis & Tools an.<br />
<br />
Dieses Diagramm zeigt recht anschaulich mit welchen Tools man welchen Problem auf den Grund gehen kann:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZO9xAjupRbLBG3MsDegdHjWu4aWz1g3vsl8WiSjDxIDDnEQaAal57BEhOU7hvQw15JvCQS-2qJNWuMHzu1I2wR4Prd0nF2EfZ4iODrZcBk-S1YkzSGdzur4uWZRRqaM6MpqFl0FGNDnQs/s1600/scalelinuxperformance-130224171331-phpapp01-dragged.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZO9xAjupRbLBG3MsDegdHjWu4aWz1g3vsl8WiSjDxIDDnEQaAal57BEhOU7hvQw15JvCQS-2qJNWuMHzu1I2wR4Prd0nF2EfZ4iODrZcBk-S1YkzSGdzur4uWZRRqaM6MpqFl0FGNDnQs/s1600/scalelinuxperformance-130224171331-phpapp01-dragged.png" height="492" width="640" /></a></div>
<br />
<br />
Links:<br />
<ul style="text-align: left;">
<li><a href="http://www.thomas-krenn.com/en/wiki/Linux_I/O_Stack_Diagram" target="_blank">http://www.thomas-krenn.com/en/wiki/Linux_I/O_Stack_Diagram</a> </li>
<li><a href="http://de.slideshare.net/brendangregg/linux-performance-analysis-and-tools" target="_blank">http://de.slideshare.net/brendangregg/linux-performance-analysis-and-tools</a></li>
</ul>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-18108738462410322692014-06-19T09:17:00.001+02:002014-06-19T09:20:37.091+02:00Monitoring: Sophos SafeGuard Enterprise<div dir="ltr" style="text-align: left;" trbidi="on">
Was ist Sophos SafeGuard Enterprise?<br />
<br />
Sophos SafeGuard Enterprise ist eine Software-Lösung für Endpoint-Security, mit der man im wesentlichen eine managed Verschlüsselungslösung für Clients aufbauen kann.<br />
<br />
Wesentliche Komponenten sind:<br />
<ul style="text-align: left;">
<li>Zertifizierte Verschlüsselungstechnologien (FIPS, Common Criteria)</li>
<li>Hohe Verschlüsselungsstärke (AES 256 Bit)</li>
<li>Festplattenverschlüsselung</li>
<li>Verschlüsselung von Wechselmedien</li>
<li>Verschlüsselter Datenaustausch, ohne dass der Empfänger selber das Produkt installiert haben muss</li>
<li>Verschlüsselung für CloudStorage (Dropbox und co) mit Zugriffsmöglichkeiten auf mobile devices</li>
<li>Verschlüsselung für Netzwerk-Freigaben</li>
<li>Unterstützung von BitLocker, FileVault etc</li>
<li>Token-basierte Authentifizierung</li>
<li>OU-basierte Zuweisung von Richtlinien</li>
<li>Client-Unterstützung: Windows XP - 8.1, MAC OSX 10.5 - 10.9</li>
<li>Datenbank-Unterstützung: SQL Server 2005 - 2012 SP1 (jeweils auch Express)</li>
<li>Management-Server: Windows Server 2003 - 2012 R2</li>
<li>Management-Konsole: Windows Server 2003 - 2012 R2, XP - 8.1 </li>
</ul>
Die Installation des Clients kann bequem mittels einer Software-Verteilung erfolgen, die Kommunikation mit dem Server erfolgt dann bidirektional (z.B. Richtlinien abrufen, Zustand hochladen), über HTTP optional mit SSL-Verschlüsselung.<br />
<br />
<br />
<br />
<br />
Die Überwachung von Sophos SafeGuard Enterprise gestaltet sich als relativ einfach, da Sophos bereits eine Web-Schnittstelle für die wichtigsten Komponenten bereitstellt:<br />
<ul style="text-align: left;">
<li>WebService (wie bereits oben beschrieben, eine sehr kritische Komponente)</li>
<li>DBAuth: Zugriff auf die Datenbank</li>
</ul>
Da der Abruf der Informationen aus Sicherheitsgründen nur über Localhost gestattet ist und der Server/Management Center nur auf einem Windows Server installiert werden kann, konnte ich, ohne Interpreter-Installation auf dem Server, leider keine meiner bevorzugten Sprachen nutzen.<br />
Daher habe ich das Plugin VBS geschrieben und bin dabei auf einen unschönen Bug in der Web-Schnittstelle gestoßen.<br />
<br />
Die Informationen der Schnittstelle werden als XML abgerufen, allerdings werden die spitzen Klammern als HTML Steuerzeichen ausgegeben und können somit nicht direkt verarbeitet werden:<br />
<br />
Falsches XML:<br />
<pre class="brush:xml;"><string xmlns="http://tempuri.org/"><?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">&lt;Dataroot&gt;&lt;WebService&gt;OK&lt;/WebService&gt;
&lt;DBAuth&gt;OK&lt;/DBAuth&gt;
&lt;Info&gt;
&lt;Database&gt;SafeGuard&lt;/Database&gt;
&lt;Server&gt;SGE1\SQLEXPRESS&lt;/Server&gt;
&lt;Version&gt;11.00.3000&lt;/Version&gt;
&lt;Name&gt;DBFactorySql on process: w3wp
Process ID: 33264&lt;/Name&gt;
&lt;Owner&gt;[dbo]&lt;/Owner&gt;
&lt;ConnectionInfo&gt;SQL Server credentials are used for authentication.&lt;/ConnectionInfo&gt;
&lt;/Info&gt;
&lt;/Dataroot&gt;</string></string></pre>
<br />
Valides XML:
<br />
<pre class="brush:xml;"><string xmlns="http://tempuri.org/"><dataroot><webservice><?xml version="1.0"?>
<string xmlns="http://tempuri.org/"><Dataroot><WebService>OK</WebService>
<DBAuth>OK</DBAuth>
<Info>
<Database>SafeGuard</Database>
<Server>SGE1\SQLEXPRESS</Server>
<Version>11.00.3000</Version>
<Name>DBFactorySql on process: w3wp
Process ID: 49588</Name>
<Owner>[dbo]</Owner>
<ConnectionInfo>SQL Server credentials are used for authentication.</ConnectionInfo>
</Info>
</Dataroot></string></webservice><info><connectioninfo></connectioninfo>
</info>
</dataroot></string>
</pre>
Durch diesen Bug musste ich im Plugin ein Tempfile erstellen (%windir%/temp) und in diesem, das XML gerade biegen.<br />
<br />
Dabei kommt dann folgendes raus:<br />
<pre class="brush:vb;">' Author: Oliver Skibbe
' Date: 2014-06-18
' Required Variables
Const PROGNAME = "check_sge"
Const VERSION = "1.0.0"
' Nagios helper functions
nsclientDir = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName)
Include nsclientDir & "\lib\NagiosPlugins.vbs"
' Create the NagiosPlugin object
Set np = New NagiosPlugin
Set WshShell = WScript.CreateObject("WScript.Shell")
Set xmlDoc = CreateObject("Msxml2.DOMDocument")
Set objFSO = CreateObject("Scripting.FileSystemObject")
' fetch xml, per default "CheckConnection" is only available via localhost
Set oXMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.3.0")
oXMLHTTP.SetOption 2, oXMLHTTP.GetOption(2) - SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
oXMLHTTP.Open "POST", "https://localhost/SGNSRV/Trans.asmx/CheckConnection", False
oXMLHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
oXMLHTTP.Send ""
' Ugly, but we have to build a Tempfile, cause SafeGuard Enterprise does not provide a valid xml file
' Sophos Support: might be fixed in 6.20
' temporary file,
strWinDir = WshShell.ExpandEnvironmentStrings("%WinDir%")
TEMPFILE = strWinDir & "\Temp\nagios_sge.xml"
' load fetched xml file
Set myFile = objFSO.CreateTextFile(TEMPFILE, True)
bodyStr = oXMLHTTP.responseXML.xml
' this is the magic, replace broken html stuff with real ">" & "<"
bodyXML = Replace(bodyStr, "<", "<")
bodyXML = Replace(bodyXML, ">", ">")
' save file
myFile.write(bodyXML)
' Website is responding and returns OK
If oXMLHTTP.Status = 200 Then
' Parse XML
xmlDoc.load(TEMPFILE)
If isObject(xmlDoc) Then
' prepare output
For Each x In xmlDoc.documentElement.selectNodes("//string/Dataroot")
WebService = x.selectSingleNode("WebService").Text
DBAuth = x.selectSingleNode("DBAuth").Text
Info = "Database: " & x.selectSingleNode("Info/Database").Text
Info = Info & vbcrlf & "DBServer: " & x.selectSingleNode("Info/Server").Text
Info = Info & vbcrlf & "DBVersion: " & x.selectSingleNode("Info/Version").Text
Info = Info & vbcrlf & "DBOwner: " & x.selectSingleNode("Info/Owner").Text
Info = Info & vbcrlf & "DBConnectionInfo: " & x.selectSingleNode("Info/ConnectionInfo").Text
Next
If WebService = "OK" And DBAuth = "OK" Then
return_code = OK
return_msg = "Everything's fine!"
Else
return_code = CRITICAL
return_msg = "Something happened!"
End If ' end if webserver and dbauth
' prepare return msg
return_msg = return_msg & " WebService: " & WebService & " DBAuth: " & DBAuth & vbcrlf & Info
Else
' XML not loaded
return_code = CRITICAL
return_msg = "XML could not be read"
End If ' end if xml load
Else
' Webservice reporting something other than 200 (OK)
MsgBox("Error: " & oXMLHTTP.Status)
return_code = CRITICAL
return_msg = "Webservice answered something strange, http status: " & oXMLHTTP.Status
End If ' end if Webservice status 200 (OK)
' exit
np.nagios_exit return_msg, return_code
' helper for including nagios lib
Sub Include( cNameScript )
Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFile = oFS.OpenTextFile( cNameScript )
ExecuteGlobal oFile.ReadAll()
oFile.Close
End Sub
' EOF
</pre>
<br />
Das Plugin wird kritisch, wenn entweder:<br />
<ul style="text-align: left;">
<li>DBAuth und/oder WebService nicht "OK" sind</li>
<li>HTTP Status != 200</li>
<li>Fehler bei der XML Verarbeitung aufgetreten sind</li>
</ul>
<br />
Download: <a href="http://exchange.nagios.org/directory/Plugins/Software/Check-SafeGuard-Enterprise/details" target="_blank">Nagios Exchange</a><br />
<br />
<br />
Bei Fragen bitte einfach melden. </div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-6766957806583580692014-06-11T16:08:00.001+02:002014-06-11T16:09:03.524+02:00Nützliche Dinge rund um die Bash und den Prompt<div dir="ltr" style="text-align: left;" trbidi="on">
Da wir Admins generell faul sind, suchen wir Wege um unsere Arbeit effizienter zu gestalten.<br />
<br />
Unter Linux gibt es da mit der Bash einige schöne Möglichkeiten, von denen ich einige mal vorstellen möchte:<br />
<br />
(Alle Beispiele gehören in die $HOME/.bash_alias, damit sie auch beim Login aktiv sind)<br />
<h4>
Farbige Manpages (kann natürlich auch in die /etc/environments eingetragen werden)</h4>
<pre class="brush:bash;">export LESS_TERMCAP_mb=$'\E[01;31m'
export LESS_TERMCAP_md=$'\E[01;31m'
export LESS_TERMCAP_me=$'\E[0m'
export LESS_TERMCAP_se=$'\E[0m'
export LESS_TERMCAP_so=$'\E[01;44;33m'
export LESS_TERMCAP_ue=$'\E[0m'
export LESS_TERMCAP_us=$'\E[01;32m'
</pre>
<br />
<h4 style="text-align: left;">
Textdateien</h4>
<pre class="brush:bash;">alias t="tail -f -n200" # t /var/log/apache2/error.log -> tail wird im fortlaufenden Modus gestartet
alias nocomment='grep -Ev '\''^(#|$)'\''' # nocomment /etc/apache2/apache2.conf -> Ausgabe der Zieldatei, allerdings ohne Kommentare
alias lvim="vim -c \"normal '0\"" # erneut die zuletzt geöffnete Datei im vim öffnen
</pre>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
Nützliche "Tools"</h4>
<pre class="brush:bash;">alias mkdir="mkdir -pv" # erstellung von rekursiven Ordnern und Anzeige der zuerstellenden Ordner
alias lsmount="mount|column -t" # formatierte Ausgabe von mount
alias path='echo -e ${PATH//:/\\n}' # formatierte Ausgabe des Path
# System
alias meminfo='free -m -l -t' # erweiterte RAM Ausgabe
alias psmem='ps auxf | sort -nr -k 4' # sortierte Ausgabe aller Prozesse nach RAM Auslastung
alias pscpu='ps auxf | sort -nr -k 3' # sortierte Ausgabe aller Prozesse nach CPU Auslastung
alias j="jobs -l" # Ausgabe der aktiven Jobs (Strg+Z, fg)
alias h="history" # Kurzform für Ausgabe der History
# Datum
alias nowtime='date +"%T"' # formatierte Ausgabe der Uhrzeit
alias nowdate='date +"%d-%m-%Y"' # formatierte Ausgabe des Datums
# Netzwerk
alias ports='netstat -tulanp' # Anzeige aller offenen Ports
# Web
alias header='curl -I' # Abruf des Headers von Argument Webseite
alias headerc='curl -I --compress' # same, allerdings mit Komprimierung
alias apache2test='/usr/sbin/apachectl -t && /usr/sbin/apachectl -t -D DUMP_VHOSTS' # Apache2 Configtest
function cdl(){ cd "$@"; ls -al;} # Bei der Nutzung von cdl, anstelle von cd, wird nun der Inhalt des Zielordners angezeigt
## Zeigt die aktuelle Verzeichnisstruktur an, sehr huebsch
function tree(){
pwd
ls -R | grep ":$" | \
sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
}
# Für die Apt Nutzer unter uns
alias upd="apt-get update" # refresh der sourcen
alias del="apt-get remove " # Entfernen (kein purge!) von Paketen
alias get="apt-get install " # Installation von Paketen
alias upg="apt-get upgrade" # Aktualisierung des Systems
alias searchpkg="apt-cache search " # Paketsuche
alias update="apt-get update && apt-get upgrade" # Refresh der Sourcen und Aktualisierung der Pakete kombiniert
</pre>
<br />
<br />
Wenn man diese Funktionen / Aliases und Variablen in der .bash_alias verankert hat, erspart man sich eine Menge Zeit und kann diese Zeit in die Weiterentwicklung der System-Landschaft stecken.<br />
<br />
Tipp: Natürlich gibt es da noch mehr Möglichkeiten, einfach mal sich selber über die Schulter schauen und überlegen ob man sein Nutzverhalten nicht mit eigenen Aliases/Funktionen noch optimieren kann<br />
<br />
<br />
Bei Fragen bitte einfach kurz melden :-)</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-13021394362565490782014-04-03T12:49:00.001+02:002014-04-03T12:49:58.931+02:00Netzwerk-Debugging mit und unter Linux<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Nachdem der letzte Blog-Eintrag schon etwas her ist, möchte ich dieses Mal etwas über (einfaches) Netzwerk-Debugging mit und unter Linux schreiben.<br />
<br />
Die typischen Kommandos ping, netstat lasse ich dabei mal außen vor, sondern gehe auf "etwas" speziellere Kommandos bzw. Alternativen ein.<br />
<br />
<b>Prüfung auf aktive Hosts/Erreichbarkeit</b><br />
<br />
Ich nutze dafür fping:<br />
Vorteile: Ip-Ranges (Range oder CIDR Notation!), Statistiken und parallele Verarbeitung!<br />
Nachteile: muss meist nachinstalliert werden<br />
<br />
1. Single Host
<br />
<pre class="brush:bash;">$ fping -s 172.16.1.91
172.16.1.91 is alive
1 targets
1 alive
0 unreachable
0 unknown addresses
0 timeouts (waiting for response)
1 ICMP Echos sent
1 ICMP Echo Replies received
0 other ICMP received
0.98 ms (min round trip time)
0.98 ms (avg round trip time)
0.98 ms (max round trip time)
0.011 sec (elapsed real time)
</pre>
2. mit IP-Range und Statisktik</div>
<pre class="brush:bash;">$ fping -s -g 172.16.1.90 172.16.1.100 -r 1
172.16.1.91 is alive
172.16.1.92 is alive
172.16.1.93 is alive
172.16.1.94 is alive
172.16.1.95 is alive
172.16.1.97 is alive
172.16.1.90 is unreachable
172.16.1.96 is unreachable
172.16.1.98 is unreachable
172.16.1.99 is unreachable
172.16.1.100 is unreachable
11 targets
6 alive
5 unreachable
0 unknown addresses
10 timeouts (waiting for response)
16 ICMP Echos sent
6 ICMP Echo Replies received
0 other ICMP received
0.38 ms (min round trip time)
0.75 ms (avg round trip time)
1.45 ms (max round trip time)
2.808 sec (elapsed real time)</pre>
<br />
<b>Verbindungen/Sessions anzeigen</b><br />
<br />
Die meisten werden wahrscheinlich netstat nutzen, ich nehme dafür "ss".<br />
"ss" ist schneller und bietet mehr Möglichkeiten in den Abfragen.<br />
<br />
<br />
<div class="level1" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 3px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px 0px 1em; padding: 0px;">
Alle Verbindungen anzeigen</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-a</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">|</span> <span class="kw2" style="color: black; font-weight: bold; margin: 0px; padding: 0px;">less</span>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">6080</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">5667</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">5668</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">11301</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 127.0.0.1:smux <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:mysql <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:sunrpc <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:http <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:ssh <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:smtp <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:iscsi <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
TIME-WAIT <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:http 172.16.0.1:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">14653</span>
TIME-WAIT <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:http 172.16.0.14:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">58166</span>
TIME-WAIT <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:http 172.16.0.14:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">58167</span>
TIME-WAIT <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:http 172.16.0.14:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">58164</span>
TIME-WAIT <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:http 172.16.0.1:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">14654</span>
TIME-WAIT <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:http 172.16.0.14:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">58165</span>
<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;"><</span>snip<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">></span></pre>
</div>
<h2 class="sectionedit5" id="lauschende_ports" style="-webkit-text-stroke-width: 0px; background-color: white; border-bottom-style: solid; border-bottom-width: 1px; border-color: rgb(204, 204, 204); clear: left; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 22px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 1em 20px; orphans: auto; padding: 0.5em 0px 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Lauschende Ports</h2>
<div class="level2" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 23px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px 0px 1em; padding: 0px;">
Alle offenen Ports auflisten</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-l</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">|</span> <span class="kw2" style="color: black; font-weight: bold; margin: 0px; padding: 0px;">less</span>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">50</span> 127.0.0.1:netbios-ssn <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">59532</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> :::sunrpc :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:sunrpc <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:http <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> :::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">38386</span> :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> :::ssh :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:ssh <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> 127.0.0.1:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">6010</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> ::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">6010</span> :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">50</span> 127.0.0.1:microsoft-ds <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">50</span> 127.0.0.1:mysql <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Nur TCP auflisten</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-lt</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">|</span> <span class="kw2" style="color: black; font-weight: bold; margin: 0px; padding: 0px;">less</span>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">50</span> 127.0.0.1:netbios-ssn <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">59532</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> :::sunrpc :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:sunrpc <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:http <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> :::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">38386</span> :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> :::ssh :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:ssh <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> 127.0.0.1:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">6010</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">128</span> ::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">6010</span> :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">50</span> 127.0.0.1:microsoft-ds <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
LISTEN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">50</span> 127.0.0.1:mysql <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Nur UDP auflisten</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-lu</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">|</span> <span class="kw2" style="color: black; font-weight: bold; margin: 0px; padding: 0px;">less</span>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:bootpc <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:sunrpc <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:ntp <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 127.0.0.1:ntp <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:ntp <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.255.255:netbios-ns <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:netbios-ns <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:netbios-ns <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.255.255:netbios-dgm <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:netbios-dgm <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:netbios-dgm <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">37222</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 127.0.0.1:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">746</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">858</span> <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>:<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> :::sunrpc :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> ::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1</span>:ntp :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> fe80::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">250</span>:56ff:feb2:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">6063</span>:ntp :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> :::ntp :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> :::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">858</span> :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span>
UNCONN <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> :::<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">38139</span> :::<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Prozess-IDs zu den jeweiligen Diensten mit anzeigen</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">ss <span class="re5" style="margin: 0px; padding: 0px;">-lp</span></pre>
</div>
<h3 class="sectionedit6" id="anzeige_mit_filterung" style="-webkit-text-stroke-width: 0px; background-color: white; border-bottom-style: none; border-color: rgb(204, 204, 204); clear: left; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 1em 40px; orphans: auto; padding: 0.5em 0px 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Anzeige mit Filterung</h3>
<div class="level3" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 43px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px 0px 1em; padding: 0px;">
Die Filter können im iproute(2)-doc nachgeschlagen werden.<br />
<br />
Nach Port:</div>
<div style="margin: 0px 0px 1em; padding: 0px;">
Alle SSH Verbindungen:</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-t</span> src :<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">22</span>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:ssh 172.16.0.12:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">62708</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Alle HTTP oder HTTPS Verbindungen</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-t</span> <span class="st_h" style="margin: 0px; padding: 0px;">'( src :80 or src: 443 )'</span>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.250:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">80</span> 172.16.0.239:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">59538</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Nach Adresse in CIDR Notation, nur TCP (-t!)</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;"><span class="co4" style="margin: 0px; padding: 0px;">$ </span>ss <span class="re5" style="margin: 0px; padding: 0px;">-t</span> dst 172.16.0.0<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">/</span><span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">24</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
oder single Host:</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;"><span class="co4" style="margin: 0px; padding: 0px;">$ </span>ss <span class="re5" style="margin: 0px; padding: 0px;">-t</span> dst 172.16.0.123</pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
oder mit Host und Port</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;"><span class="co4" style="margin: 0px; padding: 0px;">$ </span>ss <span class="re5" style="margin: 0px; padding: 0px;">-t</span> dst 172.16.0.123:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">80</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Aktive (state established) TCP-Sessions</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-t</span> state established <span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">|</span> <span class="kw2" style="color: black; font-weight: bold; margin: 0px; padding: 0px;">less</span>
Recv-Q Send-Q Local Address:Port Peer Address:Port
<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">58739</span> 172.16.0.2:microsoft-ds
<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">51709</span> 172.16.0.3:microsoft-ds
<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">39253</span> 172.16.0.3:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1025</span>
<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> 172.16.0.75:ssh 172.16.0.123:<span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">62708</span></pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Mögliche weitere States:</div>
<ul style="color: #638c9c; line-height: 1.5em; list-style-image: none; list-style-type: square; margin: 0px 0px 1em 3.5em; padding: 0px;">
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
established</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
syn-sent</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
syn-recv</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
fin-wait-1</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
fin-wait-2</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
time-wait</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
closed</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
close-wait</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
last-ack</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
closing</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
all - Alle..</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
connected - Alle verbundenen Sessions</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
synchronized - Alle verbundenen Sessions, ohne syn-sent</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
bucket - minisockets, z.B. time-wait und syn-recv.</div>
</li>
<li class="level1" style="margin: 0px; padding: 0px;"><div class="li" style="color: #333333; font-weight: normal; margin: 0px; padding: 0px;">
big - „Normale“ sockets</div>
</li>
</ul>
</div>
<h2 class="sectionedit7" id="statistiken" style="-webkit-text-stroke-width: 0px; background-color: white; border-bottom-style: solid; border-bottom-width: 1px; border-color: rgb(204, 204, 204); clear: left; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 22px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 1em 20px; orphans: auto; padding: 0.5em 0px 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Statistiken</h2>
<div class="level2" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 23px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ ss <span class="re5" style="margin: 0px; padding: 0px;">-s</span>
Total: <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">364</span> <span class="br0" style="color: #66cc66; margin: 0px; padding: 0px;">(</span>kernel <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">449</span><span class="br0" style="color: #66cc66; margin: 0px; padding: 0px;">)</span>
TCP: <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1272</span> <span class="br0" style="color: #66cc66; margin: 0px; padding: 0px;">(</span>estab <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">19</span>, closed <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1240</span>, orphaned <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1</span>, synrecv <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span>, timewait <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">1238</span><span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">/</span><span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span><span class="br0" style="color: #66cc66; margin: 0px; padding: 0px;">)</span>, ports <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">825</span>
Transport Total IP IPv6
<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">*</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">449</span> - -
RAW <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span>
UDP <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">11</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">11</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span>
TCP <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">32</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">32</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span>
INET <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">43</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">43</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span>
FRAG <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span></pre>
</div>
<h1 class="sectionedit8" id="verbindungen_mitschneiden" style="-webkit-text-stroke-width: 0px; background-color: white; border-bottom-style: solid; border-bottom-width: 1px; border-color: rgb(204, 204, 204); clear: left; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 23px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 1em; orphans: auto; padding: 0.5em 0px 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Verbindungen mitschneiden</h1>
<div class="level1" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 3px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px 0px 1em; padding: 0px;">
Bei Netzwerk/Verständnis-Problemen können Verbindungen mitgeschnitten werden, dazu wird TCPdump genutzt. Die geschriebene Datei kann dann mit WireShark verarbeitet/gelesen werden.</div>
<div style="margin: 0px 0px 1em; padding: 0px;">
Format:</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;">$ tcpdump <span class="re5" style="margin: 0px; padding: 0px;">-n</span> <span class="re5" style="margin: 0px; padding: 0px;">-i</span> <span class="re1" style="color: blue; margin: 0px; padding: 0px;">$INTERFACE</span> -s<span class="re1" style="color: blue; margin: 0px; padding: 0px;">$MAXIMALEPAKETGR</span>ÖßE <span class="re5" style="margin: 0px; padding: 0px;">-w</span> <span class="re1" style="color: blue; margin: 0px; padding: 0px;">$AUSGABEDATEI</span> <span class="re1" style="color: blue; margin: 0px; padding: 0px;">$FILTER</span>
<span class="re5" style="margin: 0px; padding: 0px;">-s</span> = maximale Paketgröße, <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">0</span> =<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">></span> <span class="nu0" style="color: #cc66cc; margin: 0px; padding: 0px;">65535</span> Bytes <span class="br0" style="color: #66cc66; margin: 0px; padding: 0px;">(</span>empfehlenswert<span class="br0" style="color: #66cc66; margin: 0px; padding: 0px;">)</span>
<span class="re5" style="margin: 0px; padding: 0px;">-n</span> = keine DNS Auflösung
<span class="re5" style="margin: 0px; padding: 0px;">-i</span> = Interface
<span class="re5" style="margin: 0px; padding: 0px;">-w</span> = Ausgabedatei</pre>
</div>
<h2 class="sectionedit9" id="filter" style="-webkit-text-stroke-width: 0px; background-color: white; border-bottom-style: solid; border-bottom-width: 1px; border-color: rgb(204, 204, 204); clear: left; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 22px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 1em 20px; orphans: auto; padding: 0.5em 0px 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Filter</h2>
<div class="level2" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 23px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px 0px 1em; padding: 0px;">
Alles was einen bestimmten Host betrifft (IP oder<span class="Apple-converted-space"> </span><abbr style="margin: 0px; padding: 0px;" title="Domain Name System">DNS</abbr>-Name)</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;"><span class="co4" style="margin: 0px; padding: 0px;">$ </span>tcpdump <span class="re5" style="margin: 0px; padding: 0px;">-ni</span> lanbond0 <span class="re5" style="margin: 0px; padding: 0px;">-w</span> ~<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">/</span>http_mitschnitt.pcap <span class="re5" style="margin: 0px; padding: 0px;">-s0</span> host 172.16.0.5</pre>
<div style="margin: 0px 0px 1em; padding: 0px;">
Alles was HTTP betrifft, ohne SSH Verbindungen</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;"><span class="co4" style="margin: 0px; padding: 0px;">$ </span>tcpdump <span class="re5" style="margin: 0px; padding: 0px;">-ni</span> lanbond0 <span class="re5" style="margin: 0px; padding: 0px;">-w</span> ~<span class="sy0" style="color: #66cc66; margin: 0px; padding: 0px;">/</span>http_mitschnitt.pcap <span class="re5" style="margin: 0px; padding: 0px;">-s0</span> port not <span class="kw2" style="color: black; font-weight: bold; margin: 0px; padding: 0px;">ssh</span> and port http</pre>
</div>
<h2 class="sectionedit10" id="beispiel" style="-webkit-text-stroke-width: 0px; background-color: white; border-bottom-style: solid; border-bottom-width: 1px; border-color: rgb(204, 204, 204); clear: left; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 22px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 1em 20px; orphans: auto; padding: 0.5em 0px 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Beispiel</h2>
<div class="level2" style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; font-family: Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; margin: 0px 0px 0px 23px; orphans: auto; padding: 0px; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px 0px 1em; padding: 0px;">
Welche Daten werden bei einem Request mittels HTTP und Host 172.16.0.5 übertragen:</div>
<pre class="code bash" style="background-color: #f7f9fa; border: 1px dashed rgb(204, 204, 204); color: #333333; font-family: monospace; font-size: 11px; margin: 0px 0px 1em; overflow: auto; padding: 0.5em; width: auto !important;"><span class="co4" style="margin: 0px; padding: 0px;">$ </span>tcpdump <span class="re5" style="margin: 0px; padding: 0px;">-ni</span> lanbond0 <span class="re5" style="margin: 0px; padding: 0px;">-w</span> ~/http_mitschnitt.pcap <span class="re5" style="margin: 0px; padding: 0px;">-s0</span> host 172.16.0.5 and port http</pre>
</div>
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-17166962877161106562014-01-06T07:58:00.001+01:002014-01-06T09:25:05.844+01:00How-To: Backup/Snapshots mehrerer Oracle Datenbanken mittels NetApp<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Um Oracle Datenbanken zu sichern gibt es mehrere Wege:<br />
<ul style="text-align: left;">
<li>RMAN (<a href="http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/rman_i_backup/index.html" target="_blank">http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/rman_i_backup/index.html</a>)</li>
<li>Datapump (<a href="http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/pump/index.html" target="_blank">http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/pump/index.html</a>)</li>
<li>Snapshots mittels NetApp, z.B. mit <a href="http://www.netapp.com/de/products/management-software/snapmanager-oracle.aspx" target="_blank">SnapManager for Oracle</a> oder eigenen Skripten</li>
</ul>
<br />
Alle Technologien haben jeweils Ihre Vor- und Nachteile, auf diese möchte ich jetzt nicht eingehen, dieses Thema behandle ich in einem weiteren Blogpost in naher Zukunft.<br />
<br />
Heute möchte ich mich auf die Sicherung mehrerer Oracle Datenbanken mittels Snapshottechnologie beziehen, welche als LUNs via ASM angebunden sind.<br />
<br />
Beim manuellen Weg würde man die Datenbank in den Backup Modus (z.B. via sqlplus als sysdba) versetzen ("<b>ALTER DATABASE BEGIN BACKUP</b>"), einen Log-Switch durchführen ("<b>ALTER SYSTEM ARCHIVE LOG CURRENT</b>"), sich dann auf die NetApp mittels SSH aufschalten und den Snapshot anlegen lassen ("<b>snap create VOLUME_NAME SNAPSHOT_NAME</b>").<br />
<br />
Dieses Verfahren mag bei einer Datenbank noch gut funktionieren, allerdings kommt man schnell in Zeitnot oder könnte einige Schritte vergessen, daher bietet es sich die Automatisierung an.<br />
<br />
Ein weiterer Effekt, den man betrachten muss, sind mehrere, unterschiedliche Datenbanken, welche voneinander abhängig sind, d.h. die den gleichen Stand haben müssen, dort sollte man dann zwingend automatisieren.<br />
<br />
Dieses habe ich im Rahmen eines Projekts gemacht und möchte hier das Perl-Skript kurz präsentieren, vielleicht hilft es noch anderen Leuten.<br />
<br />
Vorab, das Perl-Skript bietet sicher noch den einen oder anderen Optimierungsspielraum, allerdings geht es im Projektgeschäft primär um das Erfüllen der Anforderungen, das "schön" machen ist dann ein nice-to-have, falls noch Zeit über ist.<br />
<br />
Folgende Prerequisistes benötigt das Skript, welches auf dem Oracle Host ausgeführt werden soll:<br />
<ul style="text-align: left;">
<li>Anpassung der Konfigurationsvariablen in den Zeilen: 9, 22, 72, 232</li>
<li>DBD::Oracle (z.B. via <a href="http://www.cpan.org/" target="_blank">CPAN</a>, Paketmanager, <a href="http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html" target="_blank">Oracle Instant Client</a> oder eine volle Oracle Datenbank [das Skript ist auf diesen Fall konfiguriert, siehe Zeile "use lib xxx"])</li>
<li>DBI</li>
<li>Net::SSH::Expect (via <a href="http://www.cpan.org/" target="_blank">CPAN</a>)</li>
<li>Key-based SSH-Login auf der NetApp mit möglichst wenigen Rechten (wie z.B. hier beschrieben: <a href="http://cmdcmplt.wordpress.com/category/ssh-snapshot-filer-netapp-passwordless-roles/" target="_blank">http://cmdcmplt.wordpress.com/category/ssh-snapshot-filer-netapp-passwordless-roles/</a> Achtung: bei neueren OnTap Versionen wird als zusätzliches Recht: ssh-login benötigt: <i>useradmin role modify snaps -a login-ssh,cli-snap*</i>) </li>
<li>Volume-Name auf der NetApp: Diskgroup-name + Zusatz "_vol" z.B. DATA_DB1_vol</li>
</ul>
<br /></div>
<pre class="brush: perl;">#!/usr/bin/perl -w
# Author: Oliver Skibbe oliskibbe (at) gmail.com
# Date: 2014-01-06
# Purpose: Backup multiple Oracle ASM Databases with NetApp and snapshotting
#
#
use strict;
use lib "/u01/app/oracle/11.2.0.3/perl/lib/site_perl/5.10.0/x86_64-linux-thread-multi";
use DBI;
use Net::SSH::Expect;
# debug stuff
my $debug = 0;
my $self = undef;
# config stuff
my $auto_snaps = 5;
# databases to backup
my %sidhash = (
"DB1" =>
{
"data" => "DATA_DB1",
"archive" => "ARCHIVE_DB1",
"password" => 'PASSWORD'
},
"DB2" =>
{
"data" => "DATA_DB2",
"archive" => "ARCHIVE_DB2",
"password" => 'PASSWORD'
},
"DB3" => {
"data" => "DATA_DB3",
"archive" => "ARCHIVE_DB3",
"password" => 'PASSWORD'
},
); # end sidhash
### oracle connect stuff
# db handler
my $dbh = undef;
my $sth = undef;
# connect options
## ora session mode 2: sysdba
my $connecthash = { RaiseError => 0, RowCacheSize => 16, AutoCommit => 0, PrintError => 0,
ora_session_mode => 0x0002 };
my $dsn = undef;
# user & pass
my $username = "sys";
# helper arrays
my @data_arr;
my @archive_arr;
my @row;
# backup sqls
my $b_begin_backup_sql = "alter database begin backup";
my $b_end_backup_sql = "alter database end backup";
my $b_archive_log_sql = "alter system archive log current";
my $b_control_file_trace_sql = "alter database backup controlfile to trace as '/backup/controlfiles/controlfile_PLACEHOLDER.sql' reuse";
my $b_control_file_sql = "alter database backup controlfile to '/backup/controlfiles/controlfile_PLACEHOLDER.ctl' reuse";
##################################################
# SSH Stuff #
##################################################
# prepare ssh object
my $ssh = Net::SSH::Expect->new (
host => "NETAPP_HOST",
user => 'SNAPSHOT_USER',
raw_pty => 1
);
# just a little dumper
sub dump {
my $message = shift || "";
printf "%s \n", Data::Dumper::Dumper($message);
}
# begin backup, switch archive log, controlfiles
sub begin_backup {
foreach my $sid ( keys %sidhash ) {
print "START: ", $sid, "\n" if $debug;
# connect to each database
$dsn = sprintf "DBI:Oracle:%s", $sid;
$dbh = DBI->connect(
$dsn,
$username,
$sidhash{$sid}{'password'},
$connecthash) || die( "begin_backup: " . $DBI::errstr . "\n" );
# reuse sql for all SIDs
(my $sid_b_control_file_trace_sql = $b_control_file_trace_sql) =~ s/PLACEHOLDER/$sid/;
(my $sid_b_control_file_sql = $b_control_file_sql) =~ s/PLACEHOLDER/$sid/;
# begin backup
$dbh->do($b_begin_backup_sql);
# log switch
$dbh->do($b_archive_log_sql);
# controlfile trace sql
$dbh->do($sid_b_control_file_trace_sql);
# control file
$dbh->do($sid_b_control_file_sql);
# db disconnect
$dbh->disconnect if defined($dbh);
}
}
sub manage_snapshots {
my $diskgroup = shift;
my $snapshot = $ssh->exec(sprintf "snap list %s", $diskgroup);
my $snapshot_name = undef;
# if return value includes "no snapshot exists", create first snapshot
if ( $snapshot =~ /No snapshots exist/ ) {
$snapshot_name = "AUTO_${diskgroup}_1";
print "No auto shapshot for ", $diskgroup, " found, lets create ", $snapshot_name, "\n" if $debug;
} else {
# get all elements of interest
my @snapshots = $snapshot =~ /AUTO_${diskgroup}_\d+/g;
my $snapshot_count = @snapshots;
if ( $snapshot_count >= $auto_snaps ) {
# delete oldest snapshot
my $snapshot_delete = $ssh->exec(sprintf "snap delete %s %s", $diskgroup, $snapshots[-1]);
# new snapshot name
$snapshot_name = $snapshots[-1];
} elsif ( $snapshot_count == 0 ) {
$snapshot_name = "AUTO_${diskgroup}_1";
} else {
my @list;
foreach my $snapshot ( @snapshots ) {
push(@list,substr($snapshot,-1));
}
@list = sort(@list);
print "List: ", @list, "\n\n" if $debug;
my $lo = 0;
my $hi = $auto_snaps;
my $idx = 0;
for (my $cnt=$lo;$cnt<=$hi;$cnt++) {
if ($cnt == $list[$idx]) {
$idx++;
} else {
# free index will be used for name
$snapshot_name = sprintf "AUTO_%s_%s", $diskgroup, $cnt;
}
}
}
}
print "Snapshot: ", $snapshot_name, " for diskgroup ", $diskgroup, " will be created\n";
# create snapshot
my $create_snapshot = $ssh->exec(sprintf "snap create %s %s", $diskgroup, $snapshot_name);
}
sub end_backup {
my $dbh = undef;
foreach my $sid ( keys %sidhash ) {
print "END: ", $sid, "\n" if $debug;
# connect to each database
$dsn = sprintf "DBI:Oracle:%s", $sid;
$dbh = DBI->connect(
$dsn,
$username,
$sidhash{$sid}{'password'},
$connecthash) || die( "end_backup: " . $DBI::errstr . "\n" );
$dbh->{TraceLevel} = 0;
# end backup
$dbh->do($b_end_backup_sql);
# disconnect
$dbh->disconnect if defined($dbh);
}
}
# base sql to get groups and generate volume names, assumption: volume name is asm diskgroup name + _vol e.g. DATA_VISITOUR_1_vol
my $diskgroup_sql = 'SELECT
d.GROUP_NUMBER,
g.NAME AS groupname,
d.NAME,
LOWER (d.NAME)||\'_vol\' AS volume
FROM
v$asm_diskgroup g,
v$asm_disk d
WHERE
d.GROUP_NUMBER = g.GROUP_NUMBER
AND g.NAME IN (?,?,?)';
#####################################
# Begin Backup #
#####################################
begin_backup();
# prepare arrays for sql statement
foreach my $sid ( keys %sidhash ) {
push(@data_arr, $sidhash{$sid}{'data'});
push(@archive_arr, $sidhash{$sid}{'archive'});
}
# now start the ssh process
$ssh->run_ssh() or die "SSH process couldn't start: $!";
#
#$ssh->timeout(10);
sleep(3);
# you should be logged on now. Test if you received the remote prompt:
my $counter = 0;
while ($counter <= 10) {
if ($ssh->read_all(10) =~ />\s*\z/) {
# break out if login prompt
last;
} else {
$ssh->run_ssh();
}
$counter++;
}
# disable terminal translations and echo on the SSH server executing on the server the stty command:
$ssh->exec("stty raw -echo");
##################################################
# Get Diskgroups #
##################################################
$dbh = DBI->connect(
'DBI:Oracle:DB1',
$username,
$sidhash{'DB1'}{'password'},
$connecthash) || die( "get_diskgroup: " . $DBI::errstr . "\n" );
# parse and prepare query
$sth = $dbh->prepare($diskgroup_sql);
##############################
# DATA SNAPSHOTS #
##############################
# execute query for data diskgroups
$sth->execute(@data_arr);
# create snapshots for each data volume on atlas-2
while (my @row = $sth->fetchrow_array()) {
# create, delete snapshots
manage_snapshots($row[3]);
}
# executes end backup sql
end_backup();
##############################
# ARCHIVE SNAPSHOTS #
##############################
# log switch
$dbh->do($b_archive_log_sql);
# execute query for archive diskgroups
$sth->execute(@archive_arr);
# create snapshots for each archive volume on atlas-2
while (my @row = $sth->fetchrow_array()) {
# create, delete snapshots
manage_snapshots($row[3]);
}
END {
# closes the ssh connection
$ssh->close() if defined($ssh);
# closes db handler
$dbh->disconnect if defined($dbh);
}
# EOF
</pre>
<br />
<br />
Folgende Schritte führt das Skript aus:<br />
<ul style="text-align: left;">
<li>Über einen Hash (Zeile: 22) werden 1-n Datenbanken in den Backup-Modus versetzt, ein Log-Switch wird durchgeführt, ein Trace Controlfile und das Plain SQL Controlfile werden exportiert.</li>
<li>SSH Login (Zugangsdaten Zeile 72,73) zur NetApp</li>
<li>Hole alle Diskgroups, aus den konfigurierten Datenbanken (Quell-DB-Name ist dort hardcodiert, siehe Zeilen 232 und 234)</li>
<li>Starte für jede DATA Diskgroup (es wird angenommen, dass die NetApp Volumes im Format: DISKGROUP_vol benamt wurden) die Snapshoterstellung (Format: VOLNAME_1-X (siehe dazu Zeile 19, maximale Anzahl von Snapshots), der älteste Snapshot wird jeweils vorher gelöscht, wenn die maximale, konfigurierte Anzahl erreicht wurde</li>
<li>Beende Backup-Modus</li>
<li>Weiterer Log-Switch</li>
<li>Snapshoterstellung für die Archive Log Volumes im gleichen Format wie bei den Data Diskgroups</li>
<li>Ende..</li>
</ul>
<br />
Kleiner Hinweis: In der Schleifenlogik für die Erstellung der Snapshotnamen gibt es noch einen kleinen Bug, bei der Generierung des Namens für den zweiten Snapshot, hat aber keine Einschränken auf den Produktiveinsatz.<br />
<br />
Und hier natürlich noch der Download-Link: <a href="https://dl.dropboxusercontent.com/u/9482545/smo_backup.pl">https://dl.dropboxusercontent.com/u/9482545/smo_backup.pl</a><br />
<br />
<br />
Bei Fragen bitte wie immer melden.</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-66040386325288754512013-11-22T09:16:00.000+01:002013-11-22T09:20:58.591+01:00Nagios: Überwachung eines ESX Clusters und Visualisierung<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Wer einen ESX-Cluster im Hause hat, möchte sicherlich auch informiert werden, wenn dort etwas schief geht.<br />
<br />
Dazu setze ich das Plugin <a href="http://www.op5.org/community/plugin-inventory/op5-projects/check-esx-plugin" target="_blank">check_esx3.pl</a> von OP5 ein, dieses liefert, via Webschnittstelle, den Status für ein Datacenter, einzelne ESXi-Hosts oder virtuelle Maschinen.<br />
<br />
Als Abhängigkeiten hat es folgende Perl Klassen: Nagios::Plugins, File::Basename und VMware::VIRuntime (muss separat über das Perl SDK von VMWare installiert werden: <a href="https://my.vmware.com/de/web/vmware/details?productId=285&downloadGroup=VSP510-SDKPERL-510" target="_blank">https://my.vmware.com/de/web/vmware/details?productId=285&downloadGroup=VSP510-SDKPERL-510</a> ) <br />
<br />
Überblick:<br />
<br />
<pre>Usage: check_esx3.pl -D <data_center> | -H <host_name> [ -N <vm_name> ]
-u <user> -p <pass> | -f <authfile>
-l <command> [ -s <subcommand> ]
[ -x <black_list> ] [ -o <additional_options> ]
[ -t <timeout> ] [ -w <warn_range> ] [ -c <crit_range> ]
[ -V ] [ -h ]
-?, --usage
Print usage information
-h, --help
Print detailed help screen
-V, --version
Print version information
--extra-opts=[section][@file]
Read options from an ini file. See http://nagiosplugins.org/extra-opts
for usage and examples.
-H, --host=<hostname>
ESX or ESXi hostname.
-C, --cluster=<clustername>
ESX or ESXi clustername.
-D, --datacenter=<DCname>
Datacenter hostname.
-N, --name=<vmname>
Virtual machine name.
-u, --username=<username>
Username to connect with.
-p, --password=<password>
Password to use with the username.
-f, --authfile=<path>
Authentication file with login and password. File syntax :
username=<login>
password=<password>
-w, --warning=THRESHOLD
Warning threshold. See
http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT
for the threshold format.
-c, --critical=THRESHOLD
Critical threshold. See
http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT
for the threshold format.
-l, --command=COMMAND
Specify command type (CPU, MEM, NET, IO, VMFS, RUNTIME, ...)
-s, --subcommand=SUBCOMMAND
Specify subcommand
-S, --sessionfile=SESSIONFILE
Specify a filename to store sessions for faster authentication
-x, --exclude=<black_list>
Specify black list
-o, --options=<additional_options>
Specify additional command options
-t, --timeout=INTEGER
Seconds before plugin times out (default: 30)
-v, --verbose
Show details for command-line debugging (can repeat up to 3 times)
Supported commands(^ means blank or not specified parameter) :
Common options for VM, Host and DC :
* cpu - shows cpu info
+ usage - CPU usage in percentage
+ usagemhz - CPU usage in MHz
^ all cpu info
* mem - shows mem info
+ usage - mem usage in percentage
+ usagemb - mem usage in MB
+ swap - swap mem usage in MB
+ overhead - additional mem used by VM Server in MB
+ overall - overall mem used by VM Server in MB
+ memctl - mem used by VM memory control driver(vmmemctl) that controls ballooning
^ all mem info
* net - shows net info
+ usage - overall network usage in KBps(Kilobytes per Second)
+ receive - receive in KBps(Kilobytes per Second)
+ send - send in KBps(Kilobytes per Second)
^ all net info
* io - shows disk io info
+ read - read latency in ms (totalReadLatency.average)
+ write - write latency in ms (totalWriteLatency.average)
^ all disk io info
* runtime - shows runtime info
+ status - overall host status (gray/green/red/yellow)
+ issues - all issues for the host
^ all runtime info
VM specific :
* cpu - shows cpu info
+ wait - CPU wait time in ms
+ ready - CPU ready time in ms
* mem - shows mem info
+ swapin - swapin mem usage in MB
+ swapout - swapout mem usage in MB
+ active - active mem usage in MB
* io - shows disk I/O info
+ usage - overall disk usage in MB/s
* runtime - shows runtime info
+ con - connection state
+ cpu - allocated CPU in MHz
+ mem - allocated mem in MB
+ state - virtual machine state (UP, DOWN, SUSPENDED)
+ consoleconnections - console connections to VM
+ guest - guest OS status, needs VMware Tools
+ tools - VMWare Tools status
Host specific :
* net - shows net info
+ nic - makes sure all active NICs are plugged in
* io - shows disk io info
+ aborted - aborted commands count
+ resets - bus resets count
+ kernel - kernel latency in ms
+ device - device latency in ms
+ queue - queue latency in ms
* vmfs - shows Datastore info
+ (name) - free space info for datastore with name (name)
^ all datastore info
* runtime - shows runtime info
+ con - connection state
+ health - checks cpu/storage/memory/sensor status
+ maintenance - shows whether host is in maintenance mode
+ list(vm) - list of VMWare machines and their statuses
* service - shows Host service info
+ (names) - check the state of one or several services specified by (names), syntax for (names):<service1>,<service2>,...,<serviceN>
^ show all services
* storage - shows Host storage info
+ adapter - list bus adapters
+ lun - list SCSI logical units
+ path - list logical unit paths
DC specific :
* io - shows disk io info
+ aborted - aborted commands count
+ resets - bus resets count
+ kernel - kernel latency in ms
+ device - device latency in ms
+ queue - queue latency in ms
* vmfs - shows Datastore info
+ (name) - free space info for datastore with name (name)
^ all datastore info
* runtime - shows runtime info
+ list(vm) - list of VMWare machines and their statuses
+ listhost - list of VMWare esx host servers and their statuses
+ tools - VMWare Tools status
* recommendations - shows recommendations for cluster
+ (name) - recommendations for cluster with name (name)
^ all clusters recommendations
</pre>
<br />
Wie man sehen kann, lassen sich dort sehr viele Dinge überwachen, meiner Meinung nach sind Sachen wie die Auslastung (CPU, RAM, VMFS, IO, Netzwerk) und der Zustand von wichtigen VMs interessante Faktoren, die auf Probleme (Ausfälle, geringe Leistungskapazitäten, ...) hindeuten können.<br />
<br />
Dazu hier eine typische commands.cfg:</div>
<pre>
define command {
command_name check_esxi_vm_list
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l runtime -s list
}
define command {
command_name check_esxi_status
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l runtime -s status
}
define command {
command_name check_esxi_io
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l io
}
define command {
command_name check_esxi_vmfs
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l vmfs -w 10%: -c 5%:
}
define command {
command_name check_esxi_cpu
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l cpu -w 80 -c 90
}
define command {
command_name check_esxi_mem
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l mem -w 80 -c 90
}
define command {
command_name check_esxi_net
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l net
}
define command {
command_name check_esxi_vm_running
command_line $USER1$/check_esx3.pl -D $ARG1$ -H $_HOSTESX_HOSTNAME$.DOMAIN.TLD -f $ARG2$ -l runtime
}
define command {
command_name check_esxi_dc_running_hosts
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l runtime -s listhost -c 8
}
define command {
command_name check_esxi_dc_vmfs
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l vmfs -w 10%: -c 5%:
}
define command {
command_name check_esxi_dc
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l runtime
}
define command {
command_name check_esxi_dc_net
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l net
}
define command {
command_name check_esxi_dc_io
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l io
}
define command {
command_name check_esxi_dc_cpu
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l cpu
}
define command {
command_name check_esxi_dc_mem
command_line $USER1$/check_esx3.pl -D $ARG1$ -f $ARG2$ -l mem
}
</pre>
In der commands.cfg verwende ich Custom Hostvariablen, da Hosts im Nagios normalerweise über die IP angelegt werden (keine DNS Abhängigkeit..) und die IPs dann natürlich nicht im Virtual Center matchen würden, diese Host Variablen kann man ganz einfach anlegen:<br />
_ESX_HOSTNAME esx2<br />
<br />
Argument 1 muss die IP oder den Hostname des Virtual Centers enthalten, welcher die Abfragen für ein DataCenter bündeln kann.<br />
Argument 2 wäre ein Authentifizierungsfile im Format, dabei ist Domain nur nötig, wenn man AD Authentifizierung nutzt:<br />
<pre>username=foobar@domain.tld
password=barfoo</pre>
<br />
<br />
Wenn die commands.cfg nun eingebunden ist, bietet es sich an eine Hostgruppe für die Veerbung der Service Checks einzurichten (Redundanzen vermeiden!) und dieser dann die ESXi Knoten zuweisen.<br />
<br />
<br />
Nachdem nun die Service Checks eingerichtet wurden, kann die Überwachung beginnen.<br />
<br />
Nun fehlt aber noch das i-Tüpfelchen: die Visualisierung der Auslastung über alle Hosts!<br />
<br />
Dazu bediene ich mich dem großartigen <a href="http://www.pnp4nagios.org/" target="_blank">PNP4Nagios </a>(Achtung, bitte Version >= 0.6.x nutzen!), die Installation ist, durch die sehr gute Dokumentation, relativ einfach und schnell vollzogen.<br />
Zum Start gibt es bereits ein Template, welches von OP5 im PNP4Nagios mitgeliefert wird.<br />
<br />
Dieses unterstützt allerdings keine Multigraphen über mehrere Hosts, daher habe ich dafür eines selbst geschrieben, welches dann so aussieht:<br />
<br />
<img alt="" height="320" src="data:image/png;base64,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HieEENesX79etkYtXrxYvPvuu+K9996jI0VIOfP888+LU089VRx88MGiSZMmok+fPnJ/ZWWldEC++tWvSg477DBx1VVXyR8H73FvXLp9cSxatEiec+2112qP15YkNtmwcOFC0bZtW+0xQkj948MPPxQ7d+6U659++qnYsWMHHSlCypXf/e53olWrVrIJGttr164Vw4YNk+tBBwT/srp37y7OPfdc7fGwfXE8/vjjok2bNtKR27VrlzZMbUjbkUo7fkJIacHO5oTUI+BEvfjii9pjOgdh6tSp4stf/nLo8SRORbt27cSvf/1r0bJlSzFu3Lj8/mBcuriffPJJcdRRR8kWM5w/evRo33EQZdPHH38sHUOcf/bZZxf8rsXFj/3q0SHWFTgWZ7/a/tnPfiZbAo844ggxduzY/HEwY8YM0bp1a9G4cWNxxx13hKaDEFI8sLM5IfUE+eXOVcwbN27UHg9W/GvWrBFdu3aVDofueNi+KNatWye+9KUvyR+bW265RToL6liY46G2V6xYIbfh3GEb9n3wwQf544oom5YvXy7mzJkj9u3bJ/r16ycuuOCC/LHaxh9nv9r+yU9+Iq//wAMPiBNPPDF/HJx22mnikUceEXv37hVdunTRXocQUpywszkhZQ4cCFTMqMR1x1VFjw7bhx56qGw1ufLKK8WCBQt8x3XnePdFMWTIEHHcccfJ9RdeeEEceeSR4rPPPpPbYY6H2oZjc8ABB4ihQ4eKrVu35vcHMbUJ/x4bNmyY365t/HH2q23lyE6bNk3sv//++eNoLcNxOJvYfu2117TXIYQUF+xsTkg9QbW4mLZIBXn//fcLjsedEwSd13v16iXX4TDst99+8gcI23GOCPjjH/8oOnbsKA455BBxyimnSGfDexxE2TRixAjZ0R6OIvpouYw/zv64bbR+YVs5ujNnzvQdJ4QUJ+xsTkg94phjjhEvvfSS9liYg6DAvy0cx2MntQ99elQfoTi2b98u+xehzxVaggAcqfvvv18eD7aY/elPfwq1Bz9WP/7xj8XXv/71gmPKIUEY7350rEcLEJwjtIJNnjw5UfzKoVQtaYo4++McKdUihZYxbE+YMMF3nBBSnOBN5CB0pAgpU37zm9/IR2uoxLGNViEMh4D1OEcKDlTz5s3FwIED5Tr+gd11113isssu04YPgtYetAKpf27gscceky0/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tdOmfErBzjTSw++5u3AQv+duwmFpaifSjf7QriYtTtwihYn6HnnkEXHxxReLW2+9VQ5y6R2fqRxhixRFURRFlYd09XwS4A8F91n3kcKEfRg24IgjjnDi3RUr7CMVLVMbIdd22qTHdV5CpWBnGulhmccrSzvTSA/LPF5Z2plGesq1zHX1vCuMHak1a9aIp59+Wlx++eWiS5cucjwmPAYLhisX2CJFURRFUeUhXT3vCiNHCo/x9t9/f3HWWWeJhx56SDz22GMFeMOXA2yRila5/msxUSnYmUZ6WObxytLONNLDMo9XlnamkZ5yLXNdPe8KI0cKA1vee++9kXjDlwNskaIoiqKo8pCunneFdR+pIHv27BFvvPGG9lgpwxapaJXrvxYTlYKdaaSHZR6vLO1MIz0s83hlaWca6SnXMtfV865I5Eht3rxZDB8+XPaVatSokTjhhBO04UoR2+EPuOSSSy655JLL4l26HP5A+QgYP3PBggUyTmNHCnPL/OIXv5Bz1B122GHim9/8pvj6178ulixZUhC2HGCLVLTK9V+LiUrBzjTSwzKPV5Z2ppEelnm8srQzjfSUa5nr6nlbMPTBlClTpD+EF/DAwoULzTubY0DOb3/72+Ktt94Su3fvlvvLaSDOIOwjRVEURVHlIV09bwt8HwwBFdxv5EjBC/uv//ovceaZZ8rRzW+//Xbx4osvilatWvnClRNskYpWuf5rMVEp2JlGeljm8crSzjTSwzKPV5Z2ppGeci1zXT2fhIqKCjF79mzZEgWwbd1HCs8GMZ7UZZddJr7yla/IR30//elPtWFLGbZIURRFUVR5SFfPJ2XLli2yb9SqVavEtm3bknU2V2zdulWMGDFCdOvWTXu8lGGLVLTK9V+LiUrBzjTSwzKPV5Z2ppEelnm8srQzjfSUa5nr6vkkbNy4sYBaOVIAPdiHDh2qPVaK8K09LrnkkksuuSyfpcu39tBP/MMPP5SP9N577z25buxIwau74447xLe+9S0xZswY2W/qd7/7nexwft555xWEL3XYIhWtcv3XYqJSsDON9LDM45WlnWmkh2UeryztTCM95Vrmuno+CTNnzpTLTZs25UctMHakOnXqJK655hrx+OOPi2984xvycd7FF18s3n777YKw5QD7SFEURVFUeUhXzyehVo5UkyZN8pMUDxs2TFx44YWyVSoYrlxg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KzinWMrc1sasytzWTkVdl/mQIUPEWWedJe9LvHXmPadYytzWxqzK3NZORVplHgYdKUIIIYSQhNCRIoQQQghJCB0pQgghhJCE0JEihBBCCEkIHSlCCCGEkITQkUqZzZv/It5++68+pk79qzYsIYQQQkoLOlIOWL26yll67LH/E716/V106PAP0azZv0SDXO7GgbA9evxdPPzw/8k4li79H+01CCGEEFJ85Kpyv2rjSDXIeQZx6M4rNeDsDB36N+kAtWz5z1y69E5SbTnvvH9IR0s5WTpbCCGEEJIduerar9o6Uufm4gijmB0pOEfq0ZuXP/7xf8Uzz2wRBx30lFVLU1p07fqFeOGF/xXz57PlKit2794tvvvd74rTTz9dTp6Lgd7UMUxTcM4554hTTz1VTmkQHCBUB0YNPuOMM0Tbtm3l3FK6MDowyBy+U3fccUd+H+LAJM7ecOVOVHlcccUVcvoYmzxJWh6K++67T3zpS18S69at0x4nhJQXuarZr/rmSA0c+Dfx9a9n6xy5AC1jeLSoSyNxyz333CNuueWW/HQJH330Uf7Ytm3b8uuvvPKKOPnkk/PbOjBa88EHHyydoldffVVW4LpwOnAOHAQ4bJjRfO7cueL888+vd45UVHmMHz9ezJ492zhPalMeCkyqe9VVV4nnnntOe5wQUl7kqmC/snSkFi5cKC6++GJxwgmdcvTO/RAtz7cM3Xjjb8XRR/fIOQy3iDZt+uX3jx69SRx11I1ixIj1crt796HimmuezR9X4FEcHpEBtCydf/7/iP322+1zRsoBPG7U5S1xAyrrxo0by0k0dccVmKX+6aefllMq6I4rvBU3JmTFNDfY73XIwlCO1KOPPiqef/550bdvXzFo0CC5D/NTYToEtNCceeaZcgodNTcdpkfAfkyzgu0HHnhA3H333b64SwWT8lD5pDsWpDblAeDEYRoTONFXX311fj+cMswBprbnzJkjTjzxxPy2+u1DSyamw8BxdUzZj3LCdBnf+MY3ZNlFlTFAa+hJJ50kj914442+PIi6HiHEjlzV61eWjlSrVo/mvuz/53MMiD187Jce69evF1/96lfFI488IivZjh07+r4va9eula0YhxxyiFxi23u+juHDh8vHUmhZgiOECXlHjRqlDetFVbBYYv4oVJioYLEPEzl7J/V888035XG1jZYazJ01ceJE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" width="232" /><br />
<br />
<a href="http://www.blogger.com/blogger.g?blogID=8503045420193335974" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a>Der grüne Balken ist ein Ticker und zeigt dort direkt Grün, Gelb, Rot an, wenn einer der Hosts ein Problem hat, also die Thresholds überschritten wurden. <br />
<br />
Das Template bekommt ihr <a href="https://dl.dropboxusercontent.com/u/9482545/check_esxi_status.php" target="_blank">hier</a> und muss in den templates.special Ordner (z.B: /usr/share/pnp4nagios/templates.special) abgelegt und geringfügig angepasst werden:<br />
<br />
Hostnames unterstützen RegEx (z.B. 'esx' => esx1,esx2,...,esxN) oder arrays, falls die Namen kein gleiches Muster haben (array("host1","clusternode2","clusterhost1").<br />
Die ServiceNames (in meinem Fall: ESXi_XXX) müssen genau passen, damit das Special Template funktionieren kann.<br />
<br />
Bei Unsicherheiten kann man aber auch einfach die Zeilen "throw new Kohana_exception(print_r($data,TRUE));" auskommentieren und das Template über /pnp4nagios/special anschließend aufrufen, damit werden alle verfügbaren Daten ausgegeben.<br />
<br />
$services = $this->tplGetServices("HOST_NAMES", "SERVICE_NAME")<br />
In Zeile: 12 (CPU), 37 (RAM), 60 (Network)<br />
<br />
<br />
Wenn nun das Template in dem entsprechenden Ordner abgelegt ist, wird beim Aufruf des PNP4Nagios ein neuer "S" Button auf der rechten Seiten erscheinen, wenn man den auswählt, sollte das neue Template aufgelistet bzw. schon geöffnet sein.<br />
<br />
Falls nicht, bitte die Pfade, Berechtigungen und Endung (.php!) überprüfen.<br />
<br />
<br />
Et voila, die Überwachung der ESXi-Hosts / DataCenter ist eingerichtet und wird in Farbe und bunt angezeigt.<br />
<br />
<br /></div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com1tag:blogger.com,1999:blog-8503045420193335974.post-77201086522430685512013-10-28T15:42:00.001+01:002014-08-28T12:57:27.046+02:00Windows Print Server und die Druckerwarteschlange<div dir="ltr" style="text-align: left;" trbidi="on">
Ein typisches Problem in der Windows Printserver Welt scheinen fehlerhafte (=hängende) Druckeraufträge zu sein.<br />
Wenn ein Druckauftrag fehlerhaft ist, blockiert er diesen Drucker, bis dieser Druckauftrag entfernt wurde.<br />
<br />
Damit blockierte Drucker nicht durch die BenutzerInnen gemeldet werden müssen (immer unschön und wenig professionell), habe ich einen Check in VBSkript für Nagios/NSclient geschrieben, welcher alle registrierten Drucker mittels WMI auf eben diese Aufträge prüft:<br />
<br />
<pre class="brush: vb;">' MSDN: http://msdn.microsoft.com/en-us/library/aa394370%28v=vs.85%29.aspx
' Required Variables
' Author: Oliver Skibbe oliskibbe (at) gmail.com
' Date: 2013-10-30
Const PROGNAME = "check_print_spooler"
Const VERSION = "1.1.0"
' Nagios helper functions
Include "C:\Programme\NSClient++\scripts\lib\NagiosPlugins.vbs"
' Arguments
strComputer = WScript.Arguments.Item(0)
' Defaults
return_code = 0
return_msg = "Everythings fine"
' automatically kill job?
killjob = true
' Create WMI object
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
' Create the NagiosPlugin object
Set np = New NagiosPlugin
' Fetch all jobs with status error
Set Result = objWMIService.ExecQuery("Select * From Win32_PrintJob Where Status = 'Error'")
For Each instance In Result
' automatic job kill
If killjob = True Then
instance.Delete_
Else
' JobId is attached to "caption, description and name" thus we want to split and accessible with printerName(1)
printerName = Split(instance.Caption,",")
' if job should not be automatically killed, print critical and printer name
failedPrinterStr = failedPrinterStr & " " & Chr(34) & printerName(0) & Chr(34)
return_code = 2
End If
next
If return_code > 0 Then
return_msg = "Job Errors on printer " & failedPrinterStr
End If
' Nice Exit with msg and exitcode
np.nagios_exit return_msg, return_code
Sub Include( cNameScript )
Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFile = oFS.OpenTextFile( cNameScript )
ExecuteGlobal oFile.ReadAll()
oFile.Close
End Sub
</pre>
<br />
Dieses Skript sollte über einen Windows-Server z.B. über NRPE (mit <a href="http://nsclient.org/nscp/" target="_blank">NSCLIENT++</a>) aufgerufen werden und nimmt als Argument den Computernamen an.<br />
<br />
Dazu nimmt man folgende Einstellungen im NSClient vor (gilt für Version 0.38):<br />
<pre>; Script to check external scripts and/or internal aliases.
CheckExternalScripts.dll</pre>
<pre> </pre>
<pre>[NRPE]
;# NRPE PORT NUMBER
; This is the port the NRPEListener.dll will listen to.
port=5666
;# COMMAND TIMEOUT
; This specifies the maximum number of seconds that the NRPE daemon will allow plug-ins to finish executing before killing them off.
command_timeout=60
;# COMMAND ARGUMENT PROCESSING
; This option determines whether or not the NRPE daemon will allow clients to specify arguments to commands that are executed.
allow_arguments=1
[External Scripts]
check_print_spooler=cscript.exe //T:30 //NoLogo scripts\check_print_spooler.vbs $ARG1$
</pre>
Der aufmerksame Leser wird festgestellt haben, dass dem Spooler ein Argument übergeben werden kann, dieses nimmt den Namen des Servers an, das heißt man kann von einem Server aus viele andere Server angesprochen werden können, dazu muss dann allerdings der NSClient++ Dienst mit einem entsprechenden User gestartet werden, für den rein lokalen Aufruf ("." oder "localhost") reicht das Systemkonto.<br />
<br />
Im Nagios muss dann folgendes in die commands.cfg eingetragen werden:<br />
<br />
Entweder die Verteilung des Service über einen Host oder eine Hostgruppe (Argument wäre der "Hop"-Server):<br />
define command {<br />
command_name check_windows_print_spooler<br />
command_line $USER1$/check_nrpe -H $ARG1$ -c check_print_spooler -a $HOSTADDRESS$<br />
}<br />
<br />
Oder als rein lokale Variante:<br />
define command {<br />
command_name check_windows_print_spooler<br />
command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c check_print_spooler -a "."<br />
}<br />
<br />
<br />
Folgende Dinge werde ich wohl noch implementieren:<br />
<ul style="text-align: left;">
<li>Flag für automatisches Löschen der Jobs</li>
<li>E-Mail an Druckjobersteller, dass der Job abgebrochen wurde </li>
<li>Umbau auf PHP mit Nutzung von "wmic", d.h. Hop-Server wird überflüssig </li>
</ul>
<br />
* UPDATE: Damit das Skript besser skaliert, habe ich den Code etwas umgebaut und ein Flag eingebaut, welches den fehlerhaften Job automatisch löscht.<br />
<ul style="text-align: left;">
</ul>
<br />
Download: <a href="https://dl.dropboxusercontent.com/u/9482545/check_print_spooler.vbs">https://dl.dropboxusercontent.com/u/9482545/check_print_spooler.vbs</a> </div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com3tag:blogger.com,1999:blog-8503045420193335974.post-20047735481727082612013-10-28T15:06:00.001+01:002013-10-28T15:06:54.797+01:00Nachtrag zum automatischen Löschen via DBAN<div dir="ltr" style="text-align: left;" trbidi="on">
Nachdem nun endlich der Löschserver zum (sehr erfolgreichen) produktiven Einsatz gekommen ist, habe ich doch einen kleinen Fallstrick entdeckt..<br />
<br />
Was passiert wenn ich viele Geräte auf einmal einschalte? Richtig, die Sicherung kann sich verabschieden, da beim Starten der PCs erhöhte Last auf der Stromleitung stattfindet...<br />
<br />
Fazit: entweder die PCs auf verschiedene Stromkreise aufteilen oder Schritt für Schritt die PCs starten<br />
<br />
<br />
<br />
Backlink: <a href="http://oskibbe.blogspot.de/2013/07/wie-loscht-man-sicher-effizient-und.html">http://oskibbe.blogspot.de/2013/07/wie-loscht-man-sicher-effizient-und.html</a><br />
<br />
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-16073912855445298032013-10-28T14:52:00.000+01:002013-10-28T14:52:04.914+01:00Passive Sicherheit im AD mit PHP<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Ab und an kommt es mal vor, dass ein User im AD erhöhte Rechte oder zusätzliche Gruppen bekommen muss.<br />
Zum Beispiel könnte dieser erhöhte Rechte im Internet (AD-basierte Proxygruppen) oder für eine Applikation (Argh!) benötigen.<br />
<br />
Was passiert aber nun, wenn diese Rechte in Vergessenheit geraten und dadurch Schaden (z.B. Data-Loss, Malware, ...) entsteht? Die Frage ist natürlich reichlich polemisch, allerdings muss man sich die Frage stellen, wer dafür die Verantwortung trägt? Natürlich die IT.<br />
<br />
Und genau die kann dafür sorgen, dass solche Dinge NICHT in Vergessenheit geraten, indem man sich automatisch in periodischen Abständen ein Aufstellung der wichtigsten Gruppen zuschicken lässt.<br />
<br />
Genau dieses erfüllt das Skript, welches ich, aus den oben erwähnten Gefahren heraus, geschrieben habe:<br />
<br />
<br /></div>
<pre class="brush: php;">#!/usr/bin/php -q
<?php
/*
Read dom admins from AD
Author: Oliver Skibbe oliskibbe (at) gmail.com
Date: 2013-10-28
*/
function parseLdapDn($dn)
{
$dn = addcslashes( $dn, "<>" );
$result = ldap_explode_dn( $dn, 0 );
//translate hex code into ascii again
foreach( $result as $key => $value )
$result[$key] = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value);
unset($result["count"]);
return $result;
}
function sendMail ( $bodyStuff ) {
global $debug, $dryrun, $to, $replyto, $cc, $from;
// mail header
$header = "MIME-Version: 1.0\r\n";
$header .= "Content-type: text/html; charset=utf-8\r\n";
$header .= "From: " . $from . "\r\n";
$header .= "Reply-To: " . $replyto . "\r\n";
if ( $cc ) {
$header .= "Cc: " . $cc . "\r\n";
}
$header .= "X-Mailer: PHP ". phpversion();
$subject = "Mitglieder der Gruppe {$bodyStuff["name"]}";
// erfüllt seinen Zweck..
$body = "<html>
<br>
Mitglieder der Gruppe {$bodyStuff["name"]}
<br><br>
<table border=\"1\">
<tr><th align=\"left\"><b>Username</b></th><th align=\"left\"><b>OU</b></th></tr>\n\n";
unset($bodyStuff["name"]);
foreach ( $bodyStuff as $members) {
foreach ( $members as $member => $foo ) {
$body .= "<tr><td nowrap>{$member}</td><td>{$foo}</td></tr>\n";
}
}
$body .= "\n</table>
</html>";
if ( $debug || $dryrun ) {
echo "Subject " . $subject . PHP_EOL;
echo "Body: " . $body . PHP_EOL;
echo "Header: " . $header . PHP_EOL;
}
if ( ! $dryrun ) {
$result = mail( $to, $subject, $body, $header);
} else {
$result = true;
}
return $result;
}
// Variables
// debug prints
$debug = false;
// do not send mail, just print
$dryrun = false;
// receiver
$to = "oliskibbe@gmail.com";
$replyto = "ticketsystem@example.tld";
$from = "absender@example.tld";
// optional
$cc = "chef@example.tld";
// ad
$host = "ADHOST";
$user = "ADUSER";
$pass = "ADPASS";
// erlaube mehrere Gruppen z.B. Domänen-Admin und Proxy Gruppen ohne Beschränkung
$filter = "(&(|(name=Domänen-Admins)(name=FreiesInternet))(objectcategory=group))";
$dn = "dc=example,dc=local";
// nur Name und Mitglieder
$justthese = array('name', 'member');
// mit AD verbinden
$link = ldap_connect($host) or die ("Keine Verbindung zu {$host} möglich!" . PHP_EOL);
// AD Protokoll Einstellungen setzen
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($link, LDAP_OPT_REFERRALS, 0);
// Am AD anmelden
$bind = ldap_bind($link, $user, $pass) or die ("Keine Anmeldung am AD mit User {$user} an Host {$host} möglich!");
$searchresult = ldap_search ($link, $dn, $filter, $justthese );
$result = ldap_get_entries($link, $searchresult);
ldap_close($link);
// helper
foreach ( $result as $groupArray ) {
$members = array();
if (is_array ($groupArray) ) {
$members["name"] = $groupArray["name"][0];
// remove count stuff
unset($groupArray["member"]["count"]);
foreach ( $groupArray["member"] as $member ) {
$dnResult = parseLdapDn($member);
$name = str_replace("CN=","",$dnResult[0]);
unset($dnResult[0]);
$members[$members["name"]][$name] = implode(",", $dnResult);
unset($member);
unset($dnResult);
}
$result = sendMail($members);
if ( ! $result && $debug ) {
echo "Sending mail failed!";
}
}
}
</pre>
<br />
Dieses Skript fragt 1-n Gruppen über den LDAP Filter ab und verschickt wunderschöne E-Mails mit einer tabellarischen Aufstellung der entsprechenden User und in welcher OU sich diese befinden.<br />
<br />
<a href="https://dl.dropboxusercontent.com/u/9482545/check_ad_admins.php" target="_blank">Download</a><br />
<br />
Anschließend trägt man dieses Skript in die crontab ein:<br />
0 01 * * 1 /usr/bin/php -q /usr/local/bin/check_ad_admins.php<br />
<br />
Nun wird man jede Woche am Montag zum Arbeitsbeginn eine E-Mail mit den aktuellen Gruppenmitgliedern haben, bei sehr großen Firmen sollte man vielleicht noch einen Zwischenschritt einlegen und entweder eine kleine Datenbank oder ein Textfile mit Altwerten füllen um die neu hinzugekommen zu highlighten, aber in meinem Fall war das nicht nötig.<br />
<br />
<br />
Bei Fragen wie immer einfach melden.</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-59771559409364834362013-09-25T11:59:00.002+02:002013-09-25T11:59:51.010+02:00Migration von Benutzerdaten zur Umstellung von Windows XP zu Windows 7 2/2<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Die Migration der Benutzerdaten nach einer Umstellung von Windows XP auf Windows 7 ist sehr zeitaufwendig, wie ich meinem vorherigen <a href="http://oskibbe.blogspot.de/2013/09/migration-von-benutzerdaten-zur.html" target="_blank">Blog-Post</a> schon beschrieben habe.<br />
<br />
Da man in der IT, Gott sei Dank, größtenteils automatisieren kann, habe ich mir diesen Umstand zur Nutze gemacht und passend zum Sicherungs-Skript, natürlich auch ein Wiederherstellungs-Skript gebaut.<br />
<br />
Features:<br />
<ul style="text-align: left;">
<li>Außenstandorte werden unterstützt => wenn ein bestimmtes Default Gateway gesetzt ist, wird keine Wiederherstellung durchgeführt</li>
<li>Konfigurierbares Home-Laufwerk</li>
<li>Wiederherstellung nur, wenn Betriebssystem Windows7</li>
<li>Wiederherstellung nur, wenn Computername ein bestimmtes Muster hat (z.B: <b>INVW7</b>00001)</li>
<li>Wiederherstellung von Ordnern</li>
<li>Vorbereitung für Start/Stop von Prozessen</li>
<li>Error-Handling</li>
<li>Migration von OpenOffice zu LibreOffice</li>
<li>Warten auf etwaige, laufende Softwarverteilung (Frontrange DSM: Niinst32.exe)</li>
<li>Nach Wiederherstellung automatische Abmeldung </li>
<li>Flag bei erfolgte Wiederherstellung (in %APPDATA%)</li>
</ul>
</div>
<br />
Hier der Code:<br />
<br />
<pre class="brush: vb;">'#####################################################
' Wiederherstellungsscript
' Author: Oliver Skibbe oliskibbe (at) gmail.com
' Date: 2013-09-25
'#####################################################
' Constants
' Windows Version
Const Win2k = "5.0"
Const WinXP = "5.1"
Const Win2k3 = "5.2"
Const WinVista = "6.0"
Const Win7 = "6.1"
Const Win2k8 = "6.2"
' Stuff
Const Target = "INVW7"
Const HomeDrive = "Z:\"
' Objects
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objWMIService = GetObject("winmgmts:\\localhost\root\cimv2")
TargetVersion = Win7
' Get Windows Version
Set colOperatingSystem = objWMIService.ExecQuery("Select Version from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystem
Version = objOperatingSystem.Version
Next
' Quit if target pc name is not XXX or uses other Version than Windows 7
strComputerName = WshShell.ExpandEnvironmentStrings("%COMPUTERNAME%")
If InStr(1, strComputerName, Target, VbTextCompare) = 0 Then
WScript.Quit
Else
' If computer name is valid, check OS version
If Not Mid(Version,1,3) = TargetVersion Then
WScript.Quit
End If
End If ' end check valid target pc
' paths
strProfileDir = WshShell.ExpandEnvironmentStrings("%USERPROFILE%")
strProgramFilesDir = WshShell.ExpandEnvironmentStrings("%PROGRAMFILES%")
strAppDataDir = strProfileDir + "\AppData"
strLocalAppDataDir = strAppDataDir + "\Local"
strRoamingAppDataDir = strAppDataDir + "\Roaming"
' quit if restore already completed
RestoreFlag = strAppDataDir + "\Restore_done.flag"
If objFSO.FileExists(RestoreFlag) Then
WScript.Quit
End If
' Get Default GW
Set colNetworkConfiguration = objWMIService.ExecQuery("Select DefaultIPGateway from Win32_NetworkAdapterConfiguration Where IPEnabled = TRUE")
For Each objNetworkConfiguration in colNetworkConfiguration
If Not IsNull(objNetworkConfiguration.DefaultIPGateway) Then
DefaultGateway = Join(objNetworkConfiguration.DefaultIPGateway, ",")
End If
Next
' no restore in hannover so far
If DefaultGateway = "10.10.1.1" Then
Wscript.Quit
End If
' sleep if dsm net install is currently running
ProcToWatch = "NIInst32.exe"
Set colProcesses = objWMIService.ExecQuery("Select * from Win32_Process Where Name ='" & ProcToWatch & "'")
Do Until colProcesses.Count = 0
WScript.Sleep 10000
Set colProcesses = objWMIService.ExecQuery("Select * from Win32_Process Where Name ='" & ProcToWatch & "'")
Loop
' Quit if home drive is not available / writable or wrong type
CheckDrive(HomeDrive)
WshShell.Popup "Die Rück-Sicherung der eigenen Dateien wurde gestartet", 3
' Source
SourceBase = HomeDrive + "\Sicherung"
If Not objFSO.FolderExists(SourceBase) Then
MsgBox("Es wurde keine sicherung in " + SourceBase + " gefunden!")
WScript.Quit
End If
' Targets
TargetDesktop = strProfileDir & "\Desktop"
TargetOwnFiles = strProfileDir + "\Documents"
TargetFavorites = strProfileDir & "\Favorites"
TargetLOfficeBase = strLocalAppDataDir + "\LibreOffice\4\user"
TargetRoamingMSOffice = strRoamingAppDataDir + "\Microsoft"
TargetLocalMSOffice = strLocalAppDataDir + "\Microsoft"
' Restore Desktop
Restore SourceBase + "\Desktop", TargetDesktop, "Desktop", "dir", False
' Restore own files
Restore SourceBase + "\Eigene Dateien", TargetOwnFiles, "Eigene Dateien", "dir", False
' Restore Favorites
Restore SourceBase + "\Favoriten", TargetFavorites, "Favoriten", "dir", False
' Restore / Migrate OpenOffice to LibreOffice
Restore SourceBase + "\OpenOffice", TargetLOfficeBase, "LibreOffice", "dir", False
' Restore AppData Local MS Office
Restore SourceBase + "\Local\MSOffice", TargetLocalMSOffice, "MS Office", "dir", False
' Restore AppData Roaming MS Office
Restore SourceBase + "\Roaming\MSOffice", TargetRoamingMSOffice, "MS Office", "dir", False
' touch restore flag
objFSO.CreateTextFile(RestoreFlag)
WshShell.Popup "Die Rück-Sicherung der eigenen Dateien wurde beendet"
' log off
WScript.Sleep 5000
WshShell.run "shutdown /l /t 0"
' End of Main
''' Functions
' control processes
Function ProcessControl(proc, state, CheckState)
If state = "stop" Then ' stop process
cmd = "taskkill.exe /F /IM " + proc
Else ' start process
cmd = proc
End If ' end start / stop state
ExitCode = WshShell.run (cmd, 1, true)
If CheckState = True Then
If ExitCode > 0 Then
MsgBox "Fehler beim " + state + " von " + proc, vbCritical
WScript.Quit
End If ' end exit code
End If ' end check state
End Function
Function Restore(Source, Target, Label, PathType, Required)
' try to copy folder
If PathType = "dir" Then
If objFSO.FolderExists(Source) Then
If Not objFSO.FolderExists(Target) Then
CreateFolderRecursive Target
End If
objFSO.CopyFolder Source, Target
Else
' If required but does not exist: Quit!
If Required = True Then
MsgBox("Fehler bei der Rücksicherung von " + Label)
WScript.Quit
End If ' End Required Output
End If ' end check source and target folder
' try to copy file
Elseif PathType = "file" Then
' try to copy file, source file name and target directory
If objFSO.FileExists(Source) And objFSO.FolderExists(Target) Then
objFSO.CopyFile Source, Target
Else
' If required but does not exist: Quit!
If Required = True Then
MsgBox("Fehler bei der Rücksicherung von " + Label)
WScript.Quit
End If ' End Required Output
End If ' end check source and target file
' not supported
Else
MsgBox("Typ wird nicht unterstützt, wählen Sie: dir, file")
WScript.Quit
End If
End Function
' Check target drive
Function CheckDrive(Drive)
If objFSO.DriveExists(Drive) Then
Set DriveState = objFSO.GetDrive(Drive)
' Check home drive
If Not DriveState.IsReady = True Then
ErrorText = "Laufwerk " + Drive + " ist nicht erreichbar, bitte starten Sie den PC neu!"
ErrorOccured = True
Else
' 0: unkown, 1: Removable, 2: Fixed, 3: Network, 4: CD-Rom, 5: RAM-Disk
If Not DriveState.DriveType = 1 And Not DriveState.DriveType = 2 And Not DriveState.DriveType = 3 Then
ErrorText = Drive + ": ist kein gültiger Laufwerkstyp, mögliche Typen: Netzwerk, Festplatte, Wechseldatenträger"
ErrorOccured = True
End If ' end check valid drive type
End If
Else
ErrorText = "Laufwerk " + Drive + " existiert nicht, bitte starten Sie den PC neu!"
ErrorOccured = True
End If ' End Drive exists
If ErrorOccured = True Then
MsgBox(ErrorText)
WScript.Quit
End If
End Function
Function CreateFolderRecursive(FullPath)
arr = split(FullPath, "\")
path = ""
For Each dir In arr
If path <> "" Then
path = path & "\"
End If
path = path & dir
If Not objFSO.FolderExists(path) Then
objFSO.CreateFolder(path)
End If
Next
End Function
' EOF
</pre>
<br />
<br />
Das Skript sollte angepasst, getestet und im NETLOGON
Verzeichnis abgelegt werden, anschließend kann es im Login-Skript
verankert werden und stellt ab diesem Zeitpunkt automatisch bei der ersten
Anmeldung die Daten wieder her.<br />
<br />
Zum <a href="https://dl.dropboxusercontent.com/u/9482545/Wiederherstellung_Migration.vbs" target="_blank">Download</a><br />
<br />
Bei Fragen bitte melden!<br />
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-53617062912413302972013-09-17T10:18:00.002+02:002013-09-25T10:37:37.575+02:00Migration von Benutzerdaten zur Umstellung von Windows XP zu Windows 7 oder wie sichere ich automatisch für BenutzerInnen lokale Daten 1/2<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
In einem modernen Unternehmen werden häufig serverbasierte Profile und/oder Ordnerumleitungen für die persönlichen, PC-basierten, Daten der BenutzerInnen eingesetzt.<br />
<br />
Dieses hat den Vorteil, dass auf den lokalen PCs keine Daten vorhanden sind und somit die Gefahr des Datenverlustes bei Ausfall, Diebstahl, Elementare Gefährdungen, etc. minimiert wird.<br />
<br />
Wenn nun allerdings der Umstieg auf Windows 7 ansteht, wird einem bei Tests sehr schnell auffallen, dass die XP Profile nicht mit den W7 Profilen gemischt werden können und man somit, bei Anmeldung an Windows 7, nur ein temporäres Profil zugewiesen bekommt bzw. im schlimmsten Fall das XP Profil zerschiesst.<br />
Dieses Problem tritt auf, da zu einem die Registry (betrifft serverbasierte Profile) andere Einträge aufweist, sowie die Verzeichnisstruktur (z.B. Ordnerumleitungen) seit Windows Vista eine andere ist.<br />
<br />
Kurzer Exkurs zu den beiden Möglichkeiten:<br />
<h4 style="text-align: left;">
Serverbasierte Profile</h4>
<div style="text-align: left;">
Das serverbasierte Profil beinhaltet das gesamte Profil eines Benutzer-Accounts, inkl. Registry und %USERPROFILE% (genauere Informationen dazu gibt es bei Microsoft und zwar <a href="http://technet.microsoft.com/de-de/library/cc766489%28WS.10%29.aspx" target="_blank">hier</a>). Die Daten werden auf den lokalen PC geschrieben und gelesen, d.h. es findet eine Synchronisation zwischen PC und Server statt.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Vorteil(e):</div>
<ul style="text-align: left;">
<li>Alle Daten sind vollständig auf dem Server => Vermeidung von Datenverlusten</li>
<li>Alle Daten sind vollständig auf dem Client => Offline Arbeit möglich</li>
</ul>
Nachteil(e):<br />
<ul style="text-align: left;">
<li>Verzögerung beim Anmelden, da das gesamte Profil vom Server heruntergeladen, also synchronisiert wird, je nach Bandbreite und Auslastung des Servers kann dieses zu unangenehmen Verzögerungen und eingeschränktem Produktionsausfall führen. Beispiel: die Anmeldung dauert 5 Minuten mit einem serverbasierten Profil und 1 Minute mit lokalem Profil, in einem Arbeitsjahr würde sich das Ganze zu 14,7 Stunden summieren und somit pro BenutzerIn zu fast 2 Tagen Produkionsausfall per anno führen würde</li>
<li>Synchronisation der Daten erst bei Abmeldung, bei Ausfall des PCs sind die letzten Änderungen nicht gesichert, Abmeldung wird ebenfalls verzögert</li>
<li>Höhere Grundlast auf den Servern/Storage und Netzwerk zu Stoßzeiten (Beginn, Mittagspause, Feierabend)</li>
</ul>
<h4 style="text-align: left;">
Ordnerumleitungen</h4>
<div style="text-align: left;">
Ordnerumleitungen können über Gruppenrichtlinien konfiguriert werden und bieten eine einfache Möglichkeit zur Umleitung von Ordnern auf andere Systeme, gerne für Ordner wie Eigene Dateien oder Desktop genutzt, damit die Anmeldezeit verringert, aber die Gefährdung durch Datenverlust dennoch minimiert.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Vorteil(e):</div>
<ul style="text-align: left;">
<li>Konfigurierte sind vollständig auf dem Server => Vermeidung von Datenverlusten</li>
<li>Keine Verzögerung beim An- und Abmelden </li>
</ul>
Nachteil(e):<br />
<ul style="text-align: left;">
<li>Höhere Grundlast auf den Servern/Storage und Netzwerk, da Live gearbeitet wird</li>
<li>Keine Offline-Arbeit möglich </li>
</ul>
<br />
Da beide Lösungen jeweils Vor- und Nachteile bieten, sollte genau geprüft werden, welche von beiden genutzt oder wie beide kombiniert werden sollten. <br />
Typisch wird das serverbasierte Profil in Kombination mit Ordnerumleitung von Desktop und Eigene Dateien genutzt, so hat man eine effiziente Lösung mit geringem Impact auf die Datensicherheit und Gesamt Performance<br />
<br />
<br />
Zurück zum Thema, bei der Umstellung von Windows XP auf Windows 7 gibt es natürlich nicht nur die Profile/persönlichen Daten zu beachten, sondern es gilt auch Dinge zu prüfen, wie z.B.:<br />
<ul style="text-align: left;">
<li>Der wichtigste Punkt: Software-Kompabilität zu Windows 7, inkl. Architektur (Test durch IT, Fachabteilung)</li>
<li>Upgrade der Domänen-Controller (Achtung, abhängige Authentifizierungsdienste bedenken, z.B. SSPI, NTLMv1) zur Nutzung der neuen GPO Features</li>
<li>Schulung, Schulung und Schulung => erhöht Akzeptanz der Mitarbeiter, selten gilt: Neu ist immer besser ;-)</li>
<li>Planung, Planung und Planung: Test, Logistik (Wie, wo, wann und durch wen wird installiert), Rollout (Etagenweise, Abteilungsweise, ...), Transparenz (Was funktioniert wie, Wann passiert was) => Akzeptanz der Mitarbeiter</li>
</ul>
<br />
In meinem Anwendungsfall kommen keine serverbasierten Profile zum Einsatz, das hat zur Folge, das Daten wie z.B. Favoriten, Wörterbücher, Signaturen (falls nicht automatisiert, siehe dazu meine vorherigen Einträge), Dokumente nur lokal auf den PCs abgelegt werden.<br />
Es gibt nun zwei Wege um dieses "Dilema" zu lösen.<br />
Der eine Weg ist eine organisatorische Lösung, d.h. die BenutzerInnen werden informiert, dass ab sofort alle Daten auf dem Home Laufwerk gespeichert bzw. dort hin verschoben werden sollen, der andere Weg ist eine technische Lösung in Form eines Skripts, dass diese Aufgabe selbstständig erledigt.<br />
Um die größtmögliche Akzeptanz mit Effizienz zu kombinieren, habe ich mich für einen gemischten Weg entschieden, d.h. es gibt eine Dienstanweisung, die sagt, dass alles Zukünftige nur noch auf dem Home-Laufwerk gespeichert werden soll (+ Ordnerumleitungen), sowie zwei Skripte zur Sicherung und Wiederherstellung wurden von mir geschrieben.<br />
<br />
Da natürlich, aus Gründen des Datenschutz, kein Zugriff auf die Home-Laufwerke der BenutzerInnen besteht, kommt keine serverbasierte Sicherung der Daten in Frage, sondern eine Lösung, die durch den Benutzer entweder manuell oder automatisch gestartet wird.<br />
<br />
Entschieden habe ich mich für die automatische Lösung mit Hilfe des Login-Skripts, somit wird bei Login eine Sicherung der konfigurierten Pfade durchgeführt, Nachteil: die Sicherung kann unvollständig sein. Ich habe mich bewusst für das Login-Skript entschieden, da BenutzerInnen beim Herunterfahren des PCs häufig den Bildschirm als Erstes ausschalten und somit Bildschirmmeldungen nicht mehr sehen können (natürlich wäre auch eine automatisierte E-Mail aus dem Skript heraus möglich, allerdings werden diese auch gern ignoriert..)<br />
<br />
Folgende Features unterstützt das Sicherungs-Skript (durch Anpassung der Pfade und der Version kann das Skript auch als normales Sicherungsskript bei PC-Wechsel genutzt werden!):<br />
<ul style="text-align: left;">
<li>Außenstandorte werden unterstützt => wenn ein bestimmtes Default Gateway gesetzt ist, wird keine Sicherung durchgeführt</li>
<li>Konfigurierbares Home-Laufwerk</li>
<li>Sicherung nur, wenn Betriebssystem Windows XP</li>
<li>Sicherung nur, wenn Computername ein bestimmtes Muster hat (z.B: <b>PCXP</b>00001)</li>
<li>Meldung bei Überschreitung der konfigurierbaren Größe</li>
<li>Rekursive Sicherung von Ordner, bei Ausschluss von Dateien größer als X (z.B. Outlook Ordner ohne pst-file)</li>
<li>Meldung, wenn Dateien in einem Ordner gefunden werden, die zu Tag X (Datum/Meldung konfigurierbar, abhängig vom Default Gateway) erledigt sein müssen</li>
<li>Start/Stop von Prozessen</li>
<li>Error-Handling</li>
<li>Default Sicherungspfade: Desktop (250 MB), Eigene Dateien (250 MB), Outlook (pst file bis 100 MB), MS Office, OpenOffice (Textbausteine, Wörterbücher)</li>
</ul>
<br />
Hier der Code
</div>
<pre class="brush: vb;">'#####################################################
' Sicherungsscript
' Author: Oliver Skibbe oliskibbe (at) gmail.com
' Date: 2013-09-17
'#####################################################
' Constants
' Windows Version
Const Win2k = "5.0"
Const WinXP = "5.1"
Const Win2k3 = "5.2"
Const WinVista = "6.0"
Const Win7 = "6.1"
Const Win2k8 = "6.1"
' Stuff
Const Target = "INV"
Const HomeDrive = "Z:\"
' max transferred bytes
' 100 MB
Const maxDefaultSize = 104857600
' 250 MB
Const maxDesktopSize = 262144000
Const maxOwnFilesSize = 262144000
TargetVersion = WinXP
' Objects
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objWMIService = GetObject("winmgmts:\\localhost\root\cimv2")
' Get Windows Version
Set colOperatingSystem = objWMIService.ExecQuery("Select Version from Win32_OperatingSystem")
For Each objOperatingSystem In colOperatingSystem
Version = objOperatingSystem.Version
Next
' Get Default GW
Set colNetworkConfiguration = objWMIService.ExecQuery("Select DefaultIPGateway from Win32_NetworkAdapterConfiguration Where IPEnabled = TRUE")
For Each objNetworkConfiguration in colNetworkConfiguration
If Not IsNull(objNetworkConfiguration.DefaultIPGateway) Then
DefaultGateway = Join(objNetworkConfiguration.DefaultIPGateway, ",")
End If
Next
' Quit if target pc name is not XXX or uses other Version than Windows 7
strComputerName = WshShell.ExpandEnvironmentStrings("%COMPUTERNAME%")
If InStr(1, strComputerName, Target, VbTextCompare) = 0 Then
WScript.Quit
Else
' If computer name is valid, check OS version
If Not Mid(Version,1,3) = TargetVersion Then
WScript.Quit
End If
End If ' end check valid target pc
' quit if hannover gw ip => no backup
If DefaultGateway = "10.10.1.1" Then
Wscript.Quit
End If
' quit if Foobar town gw ip => no backup
If DefaultGateway = "10.16.1.1" Then
Wscript.Quit
End If
' Quit if home drive is not available / writable or wrong type
CheckDrive(HomeDrive)
' Helper vars
strProgramFiles = WshShell.ExpandEnvironmentStrings("%PROGRAMFILES%")
strProfileDir = WshShell.ExpandEnvironmentStrings("%USERPROFILE%")
strAppDataDir = WshShell.ExpandEnvironmentStrings("%APPDATA%")
strLocalDir = strProfileDir + "\Lokale Einstellungen\Anwendungsdaten"
' Source dirs
SourceDesktop = strProfileDir & "\Desktop"
SourceFavorites = strProfileDir & "\Favoriten"
SourceOwnFiles = strProfileDir + "\Eigene Dateien"
SourceOOfficeBase = strAppDataDir + "\OpenOffice.org\3\user"
SourceRoamingMSOfficeBase = strAppDataDir + "\Microsoft"
SourceLocalMSOfficeBase = strLocalDir + "\Microsoft"
' Target dirs
TargetBase = HomeDrive + "\Sicherung"
TargetDesktop = TargetBase + "\Desktop"
TargetOwnFiles = TargetBase + "\Eigene Dateien"
TargetFavorites = TargetBase + "\Favoriten"
TargetOOffice = TargetBase + "\OpenOffice"
TargetRoamingMSOffice = TargetBase + "\Roaming\MSOffice"
TargetLocalMSOffice = TargetBase + "\Local\MSOffice"
' create backup folder if not exists
If Not objFSO.FolderExists(TargetBase) Then
objFSO.CreateFolder TargetBase
End If ' End check folder
WshShell.Popup "Die Sicherung der eigenen Dateien wurde gestartet", 2
'''' Desktop ''''
BackupFolder SourceDesktop, TargetDesktop, "Desktop", maxDesktopSize, False
'''' Own files ''''
BackupFolder SourceOwnFiles, TargetOwnFiles, "Eigene Dateien", maxOwnFilesSize, False
'''' Favorites ''''
BackupFolder SourceFavorites, TargetFavorites, "Favoriten", maxDefaultSize, False
'''' OpenOffice ''''
BackupFolder SourceOOfficeBase + "\autotext", TargetOOffice + "\autotext", "OOffice Textbausteine", maxDefaultSize, False
BackupFolder SourceOOfficeBase + "\wordbook", TargetOOffice + "\wordbook", "OOffice Wörterbuch", maxDefaultSize, False
'''' Microsoft Office ''''
BackupFolder SourceRoamingMSOfficeBase + "\Templates", TargetRoamingMSOffice + "\Templates", "MS Office Templates", maxDefaultSize, False
BackupFolder SourceRoamingMSOfficeBase + "\Signatures", TargetRoamingMSOffice + "\Signatures", "MS Office Signatures", maxDefaultSize, False
BackupFolder SourceRoamingMSOfficeBase + "\Document Building Blocks", TargetRoamingMSOffice + "\Document Building Blocks", "MS Office Textbausteine", maxDefaultSize, False
'''' Outlook folder without pst (via file size) ''''
BackupFolderRecursiveExcludeMaxSize SourceRoamingMSOfficeBase + "\Outlook", TargetRoamingMSOffice + "\Outlook", "Outlook", maxDefaultSize, False
BackupFolderRecursiveExcludeMaxSize SourceLocalMSOfficeBase + "\Outlook", TargetLocalMSOffice + "\Outlook", "Outlook", maxDefaultSize, False
'''' Auftragsdaten ''''
' Message if files are available (could be just in addition to a due time)
CheckFileCountInFolder "C:\Auftragsdaten\Daten", "Auftragsdaten", 1
' Target Size Output
Set objFolder = objFSO.GetFolder(TargetBase)
' returns byte
TargetSize = objFolder.Size
WshShell.Popup "Die Sicherung der eigenen Dateien wurde beendet. Es wurden " + ConvertSize(TargetSize) + " auf Ihr Laufwerk " + HomeDrive + " übertragen", 3
' End of Main
''' Functions
' control processes
Function ProcessControl(proc, state, CheckState)
If state = "stop" Then ' stop process
cmd = "taskkill.exe /F /IM " + proc
Else ' start process
cmd = proc
End If ' end start / stop state
ExitCode = WshShell.run (cmd, 1, true)
If CheckState = True Then
If ExitCode > 0 Then
MsgBox "Fehler beim " + state + " von " + proc, vbCritical
WScript.Quit
End If ' end exit code
End If ' end check state
End Function
' Pretty output for bytes
Function ConvertSize(Size)
Do While InStr(Size,",")
CommaLocate = InStr(Size,",")
Size = Mid(Size,1,CommaLocate - 1) & _
Mid(Size,CommaLocate + 1,Len(Size) - CommaLocate)
Loop
Suffix = " B"
If Size >= 1024 Then suffix = " KB"
If Size >= 1048576 Then suffix = " MB"
If Size >= 1073741824 Then suffix = " GB"
If Size >= 1099511627776 Then suffix = " TB"
Select Case Suffix
Case " KB" Size = Round(Size / 1024, 1)
Case " MB" Size = Round(Size / 1048576, 1)
Case " GB" Size = Round(Size / 1073741824, 1)
Case " TB" Size = Round(Size / 1099511627776, 1)
End Select
ConvertSize = Size & Suffix
End Function
' return due dates e.g. till something will be done, see CheckFileCountInFolder
Function RolloutDate(DefaultGateway)
' Default
Rollout = "Offen"
Set objRolloutDates = CreateObject("Scripting.Dictionary")
' Foobar town
objRolloutDates.Add "10.16", "05.09"
' Hannover
objRolloutDates.Add "10.10", "Offen"
For Each RolloutDate In objRolloutDates
If InStr(1, DefaultGateway, RolloutDate, VbTextCompare) > 0 Then
RolloutDate = objRolloutDates(RolloutDate)
Exit Function
End If
Next
End Function
' Copy Folder
Function BackupFolder(Source, Target, Label, maxSize, Required)
' check if source exists
If objFSO.FolderExists(Source) Then
' create target folder
If Not objFSO.FolderExists(Target) Then
CreateFolderRecursive Target
End If ' End check folder
Set objFolder = objFSO.GetFolder(Source)
' returns byte
FolderSize = objFolder.Size
' copy if folder size is less than ~XXX Megabyte..
If FolderSize < maxSize Then
objFSO.CopyFolder Source, Target
Else
MsgBox(Label + " ist zu groß: " + ConvertSize(FolderSize) + ". Bitte löschen Sie unnötige Dateien oder verschieben Sie diese auf Ihr Laufwerk H:\. Falls diese Schritte nicht helfen, wenden Sie sich bitte an die Hotline")
End If ' end of size
Else
If Required = True Then
MsgBox(Label + " (" + Source + ") wurde nicht gefunden, muss aber vorhanden sein!")
WScript.Quit
End If
End If
End Function
' Copy File
Function BackupFile(Source, Filename, Target, Label, maxSize, Required)
FullPath = Source + "\" + Filename
' check if source exists
If objFSO.FileExists(FullPath) Then
' create target folder
If Not objFSO.FolderExists(Target) Then
CreateFolderRecursive Target
End If ' End check folder
Set objFile = objFSO.GetFile(FullPath)
' returns byte
FileSize = objFile.Size
' copy if folder size is less than ~XXX Megabyte..
If FileSize < maxSize Then
objFSO.CopyFile FullPath, Target + "\" + Filename
Else
MsgBox(Label + " ist zu groß: " + ConvertSize(FileSize) + ". Bitte löschen Sie diese Datei oder verschieben Sie diese auf Ihr Laufwerk H:\. Falls diese Schritte nicht helfen, wenden Sie sich bitte an die Hotline")
End If ' end of size
Else
If Required = True Then
MsgBox(Label + " (" + Source + ") wurde nicht gefunden, muss aber vorhanden sein!")
WScript.Quit
End If
End If
End Function
' check if x file(s) exist in given path
Function CheckFileCountInFolder(Path, Label, maxFiles)
FileCount = 0
If objFSO.FolderExists(Path) Then
Set objFolder = objFSO.GetFolder(Path)
Set colFiles = objFolder.Files
For Each objFile In colFiles
FileCount = FileCount + 1
Next
If maxFiles > 0 And FileCount >= maxFiles Then
MsgBox( Cstr(FileCount) + " Datei(en) in " + Label + " vorhanden, bitte bis zum " + Chr(34) + RolloutDate(DefaultGateway) + Chr(34) + " abarbeiten / entfernen oder bei der IT-Hotline melden!")
End If
End If ' end FileExists
End Function
' Copy Folder
Function BackupFolderRecursiveExcludeMaxSize(Source, Target, Label, maxSize, Required)
' check if source exists
If objFSO.FolderExists(Source) Then
' create target folder
If Not objFSO.FolderExists(Target) Then
CreateFolderRecursive Target
End If ' End check folder
Set objFolder = objFSO.GetFolder(Source)
Set Files = objFolder.Files
For Each File in Files
If Not InStr(1, File.Name, "outlook.ost", VbTextCompare) > 0 Then
If File.Size < maxSize Then
File.Copy(Target + "\" + File.Name)
Else
MsgBox(Label + " ist zu groß: " + ConvertSize(File.Size) + ". Bitte löschen Sie diese Datei oder verschieben Sie diese auf Ihr Laufwerk H:\. Falls diese Schritte nicht helfen, wenden Sie sich bitte an die Hotline")
End If
End If
Next
Else
If Required = True Then
MsgBox(Label + " (" + Source + ") wurde nicht gefunden, muss aber vorhanden sein!")
WScript.Quit
End If
End If
End Function
' Check target drive
Function CheckDrive(Drive)
If objFSO.DriveExists(Drive) Then
Set DriveState = objFSO.GetDrive(Drive)
' Check home drive
If Not DriveState.IsReady = True Then
ErrorText = "Laufwerk " + Drive + " ist nicht erreichbar, bitte starten Sie den PC neu!"
ErrorOccured = True
Else
' 0: unkown, 1: Removable, 2: Fixed, 3: Network, 4: CD-Rom, 5: RAM-Disk
If Not DriveState.DriveType = 1 And Not DriveState.DriveType = 2 And Not DriveState.DriveType = 3 Then
ErrorText = Drive + ": ist kein gültiger Laufwerkstyp, mögliche Typen: Netzwerk, Festplatte, Wechseldatenträger"
ErrorOccured = True
End If ' end check valid drive type
End If
Else
ErrorText = "Laufwerk " + Drive + " existiert nicht, bitte starten Sie den PC neu!"
ErrorOccured = True
End If ' End Drive exists
If ErrorOccured = True Then
MsgBox(ErrorText)
WScript.Quit
End If
End Function
Function CreateFolderRecursive(FullPath)
Set oFs = WScript.CreateObject("Scripting.FileSystemObject")
arr = split(FullPath, "\")
path = ""
For Each dir In arr
If path <> "" Then path = path & "\"
path = path & dir
If oFs.FolderExists(path) = False Then oFs.CreateFolder(path)
Next
End Function
' EOF</pre>
<br />
Das Skript sollte angepasst, getestet und im NETLOGON Verzeichnis abgelegt werden, anschließend kann es im Login-Skript verankert werden und sichert ab diesem Zeitpunkt automatisch bei jeder Anmeldung die Daten.<br />
<br />
Zum <a href="https://dl.dropboxusercontent.com/u/9482545/Sicherung_Migration.vbs" target="_blank">Download</a><br />
<br />
Bei Fragen bitte melden!<br />
<br /></div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-63048757563629750842013-08-22T16:41:00.001+02:002013-08-22T16:41:04.300+02:00Outlook Signaturen und wie bekämpft man die Anarchie 2/2<div dir="ltr" style="text-align: left;" trbidi="on">
Wie bereits im letzten <a href="http://oskibbe.blogspot.de/2013/08/outlook-signaturen-und-wie-bekampft-man.html" target="_blank">Blogpost</a> als mögliches, bzw. typisches Problem erwähnt, müssen für eine saubere Signatur vollständige Daten im AD enthalten sein.<br />
<br />
Dazu kann man entweder auf die Mitarbeiter vertrauen, dass diese sich immer melden, wenn sich etwas ändert oder man beschäft je nach Unternehmensgröße einfach eine Vollzeitstelle damit, welche den ganzen Tag durchs Haus läuft und alle Mitarbeiter "inventarisiert"...natürlich nur ein Spaß.. ;-)<br />
<br />
Die, meiner Meinung nach, sinnvollste Lösung ist die <b>kontrollierte </b>Selbstpflege durch die BenutzerInnen selbst, dazu stellt man ihnen ein Tool bereit welches die Daten abfragt und speichert.<br />
<br />
Vorteile:<br />
<ul style="text-align: left;">
<li>weniger Hotlineanrufe</li>
<li>BenutzerInnen möchten die Daten selbst ändern, damit z.B. ihre Signatur aktuell ist</li>
</ul>
<br />
Ich habe mich dabei für eine PHP Web-Applikation entschieden, da diese unabhängig vom Computer und vom Server ist, da es PHP für ebenso für Windows gibt.<br />
<br />
Im Anwendungsfall habe ich mich für einen netten, kleinen Ubuntu 12.04 LTS Server mit <a href="http://de.wikipedia.org/wiki/LAMP_%28Softwarepaket%29" target="_blank">LAP </a>Stack (ja, der heißt normalerweise LAMP, allerdings benötige ich keinen MySQL-Server.. ;-)) entschieden, da ich eine gewissen Open-Source Affinität habe, Lizenzkosten sparen möchte und sehr gute Erfahrung damit gemacht habe.<br />
Dieser authentifiziert die Benutzer mittels <a href="http://de.wikipedia.org/wiki/Kerberos_%28Informatik%29" target="_blank">Kerberos</a> über den Apache2 am AD (voraussichtlich folgt dazu ein kleines Tutorial im nächsten Post), anschließend übernimmt PHP den Benutzernamen über die Server Variable REMOTE_USER.<br />
<br />
Da die Code-Menge dem Leserahmen sprengen würde, gibt es dieses Mal nur einen Direkt-Download als Zip-Archiv: <a href="https://dl.dropboxusercontent.com/u/9482545/webapp_signatur.zip">https://dl.dropboxusercontent.com/u/9482545/webapp_signatur.zip</a><br />
<br />
Das Zip-Archiv muss auf das Zielsystem in einen, für den Webserver lesbaren Pfad gepackt werden (je nach Distribution: /var/www, /srv/htdocs, ...).<br />
<br />
Features:<br />
<ul style="text-align: left;">
<li>1-N Standorte können konfiguriert / vorbereitet werden</li>
<li>Schreiben auf den jeweilig konfigurierten, lokalen DC (bei mehreren Standorten, damit nach Neuanmeldung das Signatur Generierungsskript die aktuellen Daten bekommt)</li>
<li>Generierung der Adressdaten über die Auswahl des Standorts, auch bei mehreren Standorten pro Stadt</li>
<li>Generierung der Fax-/Telefonnummer über die Auswahl des Standorts, es wird nur die Durchwahl eingegeben => einheitliche Formatierung</li>
<li>Handynummer wird über Auswahl der Vorwahl+Rufnummer generiert => einheitliche Formatierung</li>
<li>Unterstützung für Unterfirmen, abhängig vom Standort (z.B. Wayne Enterprises Hannover, Wayne Business Berlin) => unterschiedliche Einträge in die Firmenfelder</li>
<li>Unterstützung von Geschäftsbereichen/Abteilungen und Job-Titeln<br /></li>
</ul>
<br />
Folgende Schritte müssen erfüllt werden, damit das ganze lauffähig wird:<br />
<ul style="text-align: left;">
<li>Geringe PHP Kenntnisse</li>
<li>Fortgeschrittene Linux Kenntnisse (für Kerberos Authentifizierung )</li>
<li>Installation Apache2 mit PHP (+ LDAP Module) und Authentifizierung (Zugriff auf REMOTE_USER) z.B. Kerberos oder mod_sspi (nur für Win32 und Apache2 2.0/2.2)</li>
<li>Anpassung der Konfiguration in config.inc.php nach eigenem Ermeßen.</li>
<li>Anpassung der index.php für CI-Anpassungen</li>
</ul>
<br />
Einen Schönheitsfehler gibt es allerdings noch, die Übertragung wird per Ajax durchgeführt und der Return vom Speichern zurück zur Index.php funktioniert noch nicht perfekt.<br />
<br />
Da die Daten im AD nun im Laufe der Zeit aktualisiert werden, kann man aus diesen z.B. genauso leicht eine Telefonliste genieren.<br />
<br />
<br />
Bei Fragen bitte wie immer einfach melden. ;-)<br />
<br /></div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-87523957784372345672013-08-22T10:11:00.000+02:002013-08-22T10:13:13.773+02:00Outlook Signaturen und wie bekämpft man die Anarchie 1/2<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Da es häufiger vorkommt, dass in einem großen Unternehmen BenutzerInnen innerhalb des Unternehmens oder der Standorte umziehen, ändern sich dementsprechend die Benutzerdaten und die Signatur, zu dem sieht jede Signatur irgendwie anders aus.<br />
<br />
<br />
Mögliche Probleme:<br />
<ul style="text-align: left;">
<li>Anarchie bei der Signaturerstellung (z.B. Telefonnummernformat, Grußformel, usw.), Corporate Identity soll erreicht werden</li>
<li>Aktualität der Daten, siehe dazu meinen nächsten Blogpost => Wie halte ich die AD-Daten aktuell, bzw. lasse es die machen, die wissen sollten wo sie sitzen -> die BenutzerInnen</li>
</ul>
<br />
Damit man diese Signatur nicht bei jeder Person manuell erstellen muss, gibt es verschiedene Möglichkeiten diese zu verteilen.<br />
<br />
Folgende Fakten haben wir:<br />
<ul style="text-align: left;">
<li>Outlook Signatur liegt im Standard in %APPDATA% => C:\Users\%username%\AppData\Roaming\Microsoft\Signatures)</li>
<li>Active-Directoy mit aktuellen Daten (dazu komme ich im nächsten Blogpost ;-)) => Größtes Problem</li>
<li>Signatur soll weiterhin anpassbar sein oder auch nicht => großer, technischer Unterschied!</li>
</ul>
<br />
Folgende Verteilungsmöglichkeiten sind mir dabei in den Sinn gekommen:<br />
<br />
<h3 style="text-align: left;">
<b>1.</b> Verteilung einer fertigen Signatur</h3>
Signatur wird per Skript auf dem NETLOGON Laufwerk erzeugt und per Login-Skript verteilt.<br />
Die Zuweisung würde über die Registry erfolgen:<br />
<ul style="text-align: left;">
<li> Zuweisung über den "offiziellen" Weg (KB: <a href="http://support.microsoft.com/kb/2691977">2691977</a>), <b>HKEY_CURRENT_USER\Software\Microsoft\Office\</b><b><i>x.0</i></b><b>\Common\MailSettings </b>Nachteil: BenutzerInnen können ihre Signatur nicht mehr in Outlook anpassen. </li>
<li> Zuweisung über den inoffiziellen Weg, direkt in das Profil des Benutzers:
<b>HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows
Messaging
Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\0000000<span style="color: red;">1</span> </b>("1" bedeutet Kontonummer, im Unternehmen normalerweise die 1) Vorteil: Benuter können Ihre Signaturen selber setzen, Nachteil: Signaturnamen liegen als Binary Type im Hex Format vor ("00 4D" => "M") und somit etwas komplizierter zu implementieren</li>
</ul>
Vorteile:klar definierte Signatur, Zuweisung über Login-Skript einfach möglich, da Domänen-Benutzer in HKCU schreiben dürfen<br />
Nachteil: statisch, da aktualisierte Signatur erst verfügbar, wenn der nächste Genierungslauf durch ist<br />
<br />
<br />
<h3 style="text-align: left;">
<b>2. Generierung der Signatur über ein VBSkript im Login-Skript.</b></h3>
Die Zuweisung würde hierbei entweder über die Registry Keys oder über die VB Funktionen erfolgen.<br />
Vorteile: lesbarer Code ohne Registry Zugriffe, Generierung der Signatur bei Login<br />
Nachteile: weiteres Skript muss über das Login-Skript aufgerufen werden<br />
<br />
<br />
Für meinen Anwendungsfall habe ich mich für die zweite Variante entschieden, da diese deutlich einfacher zu warten ist.<br />
<br />
Dazu hier der Code für die Signatur-Generierung (Download via Dropbox: <a href="https://dl.dropboxusercontent.com/u/9482545/Outlook_signatur.vbs">https://dl.dropboxusercontent.com/u/9482545/Outlook_signatur.vbs</a>) :<br />
<br />
<br /></div>
<pre class="brush: vb;">' Objects
Set objSysInfo = CreateObject("ADSystemInfo")
Set WshShell = CreateObject("WScript.Shell")
Set objUser = GetObject("LDAP://" & objSysInfo.UserName)
Set objWord = CreateObject("Word.Application")
' Signature stuff
strName = objUser.givenName + " " + objUser.sn
strDepart = objUser.Department
strDesc = objUser.Description
strStreet = objUser.StreetAddress
strLocation = objUser.l
strPostCode = objUser.PostalCode
strPhone = objUser.TelephoneNumber
strMobile = objUser.Mobile
strFax = objUser.FacsimileTelephoneNumber
strEmail = objUser.mail
strCompany = objUser.Company
aQuote = Chr(34)
aNewLine = Chr(11)
If strCompany = "Dummyhausen" then
strCompanyTitle = "Foobar company Dummyhausen"
strCompanyWeb = "http://www.specialpage.de"
Else
strCompanyTitle = "Foobar company"
strCompanyWeb = "http://www.foobar.de"
End If
Set objDoc = objWord.Documents.Add()
Set objSelection = objWord.Selection
Set objEmailOptions = objWord.EmailOptions
Set objSignatureObject = objEmailOptions.EmailSignature
Set objSignatureEntries = objSignatureObject.EmailSignatureEntries
objSelection.Font.Name = "Arial"
objSelection.Font.Size = 10
objSelection.TypeText "Mit freundlichem Gruß"
objSelection.TypeText vbCrLf
if (strCred) Then objSelection.TypeText strCred & strName Else objSelection.TypeText strName
objSelection.TypeText vbCrLf & vbCrLf
' Bold
objSelection.Font.Bold = True
objSelection.TypeText strCompanyTitle + aNewLine
objSelection.TypeText strDepart
objSelection.Font.Bold = False
' not bold
objSelection.TypeText vbCrLf & vbCrLf
if (strCred) Then objSelection.TypeText strCred & strName Else objSelection.TypeText strName
objSelection.TypeText aNewLine
objSelection.TypeText strDesc
objSelection.TypeText vbCrLf
objSelection.TypeText strStreet & aNewLine
objSelection.TypeText strPostCode & " " & strLocation & aNewLine
objSelection.TypeText "Tel: " & strPhone & aNewLine
if (strFax) Then objSelection.TypeText "Fax: " & strFax & aNewLine
if (strMobile) Then objSelection.TypeText "Mobil: " & strMobile & aNewLine
objSelection.TypeText vbCrLf
objDoc.Hyperlinks.Add objSelection.Range, "Mailto:" & strEmail, , , strEmail
objSelection.TypeText " | "
objDoc.Hyperlinks.Add objSelection.Range, strCompanyWeb, , ,strCompanyWeb
objSelection.TypeText vbCrLf
objSelection.TypeText "________________________________"
objSelection.TypeText vbCrLf & vbCrLf
objSelection.TypeText "Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet."
objSelection.TypeText vbCrLf & vbCrLf
objSelection.TypeText "This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorised copying, disclosure or distribution of the material in this e-mail is strictly forbidden."
objSelection.TypeText vbCrLf
Set objSelection = objDoc.Range()
' full signature
objSignatureEntries.Add "Full Signature", objSelection
objSignatureObject.NewMessageSignature = "Full Signature"
objDoc.Saved = True
' reply signature
objSignatureEntries.Add "Reply Signature", objSelection
objSignatureObject.ReplyMessageSignature = "Reply Signature"
objDoc.Saved = True
' EOF
</pre>
<br />
Dieses Skript hat keinerlei Ausgaben, sondern verrichtet die Arbeit komplett im Hintergrund, somit werden die BenutzerInnen nicht belästigt, im Beispiel wird die gleiche Signatur für die "Antwort Signatur" genommen, das könnte man noch aufteilen, in dem man eine Kurzsignatur dazu entwirft, mit dem Beispiel sollte man das eigentlich einfach hinbekommen.<br />
<br />
Es nutzt die Office VBSkript Bibliotheken und liest die eigenen Benutzerdaten aus dem AD.<br />
<br />
<br />
Nun muss das Skript nur noch in das Login-Skript eingebaut werden, anschließend werden bei allen PC-Anmeldungen die Signaturen neugeschrieben und aktiviert.<br />
<br />
<br />
Fazit: Ohne großen Aufwand kann die Corporate Identity durchgesetzt werden.<br />
<br />
Download-Link: <a href="https://dl.dropboxusercontent.com/u/9482545/Outlook_signatur.vbs">https://dl.dropboxusercontent.com/u/9482545/Outlook_signatur.vbs</a><br />
<br />
<br />
Bei Fragen bitte einfach melden!<br />
<br />
<br />
Im zweiten Teil wird es um die vereinfachte Aktualisierung der AD BenutzerInnen Daten gehen.<br />
<br /></div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-34178247618301826502013-07-30T09:08:00.001+02:002013-07-30T09:17:51.071+02:00Wie überwache ich Fortinet FortiGate Appliances<div dir="ltr" style="text-align: left;" trbidi="on">
Da wir hier im Hause diverse <a href="http://www.fortinet.com/" target="_blank">Fortinet </a>FortiGate, teilweise als Active/Passive Cluster, betreiben, liegt es natürlich nahe, dass diese Appliances ebenfalls mit in die Überwachung aufgenommen werden.<br />
<br />
Kurzer Exkurs:<br />
Die bei uns eingesetzten Fortinet FortiGates gehören zur Klasse der UTM Geräte (Unified Threat Management) und bieten unter anderem folgende Features:<br />
<ul style="text-align: left;">
<li>IPS - Intrusion Prevention</li>
<li>AntiVirus - Automatisierte Überprüfung auf Viren für z.B: HTTP, SMTP, POP3, IMAP, FTP</li>
<li>VPN - IPSec / SSL, inkl. 2-Faktor Authentifizierung</li>
<li>Proxy - inkl. Web-Filtering, SSO über LDAP/Radius bzw. SSO Client auf DC</li>
<li>Deep Packet Inspection</li>
<li>Firewall</li>
<li>Routing</li>
<li>IPv4 & IPv6</li>
</ul>
<br />
Da mir die existierenden Fortinet Checks nicht wirklich gefallen haben (Code-Qualität, Art der Aufrufe, Funktionsumfang), habe ich mich entschieden ein eigenes Plugin in Perl zu schreiben (Download auf <a href="http://exchange.nagios.org/directory/Plugins/Hardware/Network-Gear/Fortinet/check_fortigate-2Epl/details" target="_blank">exchange.nagios.org</a>):<br />
<br />
Zum jetztigen Stand unterstützt es:<br />
<ul style="text-align: left;">
<li>CPU</li>
<li>Memory</li>
<li>Sessions</li>
<li>VPN</li>
<li>Cluster-Zustand</li>
</ul>
<h3 style="text-align: left;">
Beschreibung:</h3>
<br />
NAME
<br />
Check Fortinet FortiGate Appliances
<br />
<br />
SYNOPSIS
<br />
check_fortigate.pl -H -C -T [-w|-c|-S|-s|-R|-M|-V|-?]
<br />
Options:
<br />
<br />
-H --host STRING or IPADDRESS Check interface on the indicated host
<br />
-C --community STRING Community-String for SNMP
<br />
-T -- type STRING CPU, MEM, Ses, VPN, Cluster
<br />
-S --serial STRING Primary serial number
<br />
-s --slave get values of slave
<br />
-w --warning INTEGER Warning threshold, applies to cpu, mem, session.
<br />
-c --critical INTEGER Critical threshold, applies to cpu, mem, session.
<br />
-R --reset Resets ip file (cluster only)
<br />
-M --mode STRING Output-Mode: 0 => just print, 1 => print and show failed tunnel, 2 => critical
<br />
-V --vpnmode STRING VPN-Mode: both => IPSec & SSL/OpenVPN, ipsec => IPSec only, ssl => SSL/OpenVPN only
<br />
-? --help Returns full help text
<br />
<br />
OPTIONS
<br />
-H--host
<br />
STRING or IPADDRESS - Check interface on the indicated host.
<br />
<br />
-C|--community
<br />
STRING - Community-String for SNMP
<br />
<br />
-T|--type
<br />
STRING - CPU, MEM, Ses, VPN, Cluster
<br />
<br />
-S|--serial
<br />
STRING - Primary serial number.
<br />
<br />
-s|--slave
<br />
BOOL - Get values of slave
<br />
<br />
-w|--warning
<br />
INTEGER - Warning threshold, applies to cpu, mem, session.
<br />
<br />
-c|--critical
<br />
INTEGER - Critical threshold, applies to cpu, mem, session.
<br />
<br />
-R|--reset
<br />
BOOL - Resets ip file (cluster only)
<br />
<br />
-M|--mode
<br />
STRING - Output-Mode: 0 => just print, 1 => print and show
<br />
failed tunnel, 2 => critical
<br />
<br />
-V|--vpnmode
<br />
STRING - VPN-Mode: both => IPSec & SSL/OpenVPN, ipsec => IPSec
<br />
only, ssl => SSL/OpenVPN only<br />
<br />
<br />
<h3 style="text-align: left;">
Der Code:</h3>
<pre class="brush: perl;">#!/usr/bin/perl
# This Plugin checks the cluster state of FortiGate
# Tested on: FortiGate 100D / FortiGate 300C (both 5.0.3)
#
# Author: Oliver Skibbe (oliskibbe (at) gmail.com)
# Date: 2013-07-29
#
# Changelog:
# - initial release (cluster, cpu, memory, session support)
# - added vpn support, based on check_fortigate_vpn.pl: Copyright (c) 2009 Gerrit Doornenbal, g(dot)doornenbal(at)hccnet(dot)nl
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# If you wish to receive a copy of the GNU General Public License,
# write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-130
# Description:
use strict;
use Net::SNMP;
use List::Compare;
use Switch;
use Getopt::Long qw(:config no_ignore_case bundling);
use Pod::Usage;
# Parse out the arguments...
my ($ip, $community, $type, $warn, $crit, $slave, $pri_serial, $reset_file, $mode, $vpnmode) = parse_args();
# Initialize variables....
my $net_snmp_debug_level = 0x0; # See http://search.cpan.org/~dtown/Net-SNMP-v6.0.1/lib/Net/SNMP.pm#debug()_-_set_or_get_the_debug_mode_for_the_module
# for more information.
my %status = ( 'UNKNOWN' => '-1', # Enumeration for the output Nagios states
'OK' => '0',
'WARNING' => '1',
'CRITICAL' => '2' );
## SNMP ##
my ($session, $error) = get_snmp_session($ip, $community); # Open an SNMP connection...
## OIDs ##
my $oid_unitdesc = ".1.3.6.1.2.1.1.1.0"; # Location of Fortinet device description... (String)
my $oid_serial = ".1.3.6.1.2.1.1.5.0"; # Location of Fortinet serial number (String)
my $oid_cluster_type = ".1.3.6.1.4.1.12356.101.13.1.1.0"; # Location of Fortinet serial number (String)
my $oid_cluster_serials = ".1.3.6.1.4.1.12356.101.13.2.1.1.2"; # Location of Cluster serials (String)
# Generic my $oid_cpu = ".1.3.6.1.4.1.12356.101.4.1.3.0"; # Location of CPU (%)
my $oid_mem = ".1.3.6.1.4.1.12356.101.13.2.1.1.4"; # Location of cluster member Mem (%)
# Generic my $oid_mem = ".1.3.6.1.4.1.12356.101.4.1.4.0"; # Location of Mem (%)
my $oid_cpu = ".1.3.6.1.4.1.12356.101.13.2.1.1.1"; # Location of cluster member CPU (%)
# Generic my $oid_ses = ".1.3.6.1.4.1.12356.101.4.1.8.0"; # Location of Sessions (int)
my $oid_ses = ".1.3.6.1.4.1.12356.101.13.2.1.1.6"; # Location of cluster member Sessions (int)
# VPN OIDs
my $oid_ActiveSSL = ".1.3.6.1.4.1.12356.101.12.2.3.1.2.1"; # Location of Fortinet firewall SSL VPN Tunnel connection count
my $oid_ActiveSSLTunnel = ".1.3.6.1.4.1.12356.101.12.2.3.1.6.1"; # Location of Fortinet firewall SSL VPN Tunnel connection count
my $oid_ipsectuntableroot = ".1.3.6.1.4.1.12356.101.12.2.2.1"; # Table of IPSec VPN tunnels
my $oidf_tunstatus = ".20"; # Location of a tunnel's connection status
my $oidf_tunndx = ".1"; # Location of a tunnel's index...
my $oidf_tunname = ".3"; # Location of a tunnel's name...
## Stuff ##
my $state; # return state
my $path = "/usr/lib/nagios/plugins/FortiSerial"; # path to store serial filenames
my $filename = $path . "/" . $ip; # file name to store serials
my $oid; # helper var
my $value; # helper var
my $string; # return string
my $perf; # performance data
# Check SNMP connection and get the description of the device...
my $curr_device = get_snmp_value($session, $oid_unitdesc);
# Check SNMP connection and get the serial of the device...
my $curr_serial = get_snmp_value($session, $oid_serial);
switch ( lc($type) ) {
case "cpu" { ($state, $string) = get_health_value($oid_cpu, "CPU", "%"); }
case "mem" { ($state, $string) = get_health_value($oid_mem, "Memory", "%"); }
case "ses" { ($state, $string) = get_health_value($oid_ses, "Session", ""); }
case "vpn" { ($state, $string) = get_vpn_state(); }
else { ($state, $string) = get_cluster_state(); }
}
# Close the connection
close_snmp_session($session);
# exit with a return code matching the state...
print $string."\n";
exit($status{$state});
########################################################################
## Subroutines below here....
########################################################################
sub get_snmp_session{
my $ip = $_[0];
my $community = $_[1];
my ($session, $error) = Net::SNMP->session(
-hostname => $ip,
-community => $community,
-port => 161,
-timeout => 5,
-retries => 3,
-debug => $net_snmp_debug_level,
-version => 2,
-translate => [-timeticks => 0x0] #schaltet Umwandlung von Timeticks in Zeitformat aus
);
return ($session, $error);
} # end get snmp session
sub get_health_value {
my $label = $_[1];
my $UOM = $_[2];
if ( $slave == 1 ) {
$oid = $_[0] . ".2";
$label = "slave_" . $label;
} else {
$oid = $_[0] . ".1";
}
$value = get_snmp_value($session, $oid);
if ( $value > $crit ) {
$state = "CRITICAL";
$string = $label . " is critical: " . $value . $UOM;
} elsif ( $value > $warn ) {
$state = "WARNING";
$string = $label . " is warning: " . $value . $UOM;
} else {
$state = "OK";
$string = $label . " is okay: " . $value. $UOM;
}
$perf = "|'" . lc($label) . "'=" . $value . $UOM . ";" . $warn . ";" . $crit;
$string = $state . ": " . $curr_device . " (Master: " . $curr_serial .") " . $string . $perf;
return ($state, $string);
} # end health value
sub get_cluster_state {
my @help_serials; # helper array
# get all cluster member serials
my %snmp_serials = %{get_snmp_table($session, $oid_cluster_serials)};
my $cluster_type = get_snmp_value($session, $oid_cluster_type);
my %cluster_types = (1 => "Standalone", 2 => "Active/Active", 3 => "Active/Passive");
# first time, write cluster members to helper file
if ( ! -e $filename || $reset_file ) {
# open file handle to write (create/truncate)
open (SERIALHANDLE,"+>$filename") || die "Error while creating $filename";
# write serials to file
while (($oid, $value) = each (%snmp_serials)) {
print (SERIALHANDLE $value . "\n");
}
}
# snmp serials
while (($oid, $value) = each (%snmp_serials)) {
chomp; # remove "\n" if exists
push @help_serials, $value;
}
# if less then 2 nodes found: critical
if ( scalar(@help_serials) < 2 ) {
$string = "HA (" . $cluster_types{$cluster_type} . ") inactive, single node found: " . $curr_serial;
$state = "CRITICAL";
# else check if there are differences in ha nodes
} else {
# open existing serials
open ( SERIALHANDLE, "$filename") || die "Error while opening file $filename";
my @file_serials = <SERIALHANDLE>; # push lines into file_serials
chomp(@file_serials); # remove "\n" if exists in array elements
close (SERIALHANDLE); # close file handle
# compare serial arrays
my $comparedList = List::Compare->new('--unsorted', \@help_serials, \@file_serials);
if ( $comparedList->is_LequivalentR ) {
$string = "HA (" . $cluster_types{$cluster_type} . ") is active";
$state = "OK";
} else {
$string = "Unknown node in active HA (" . $cluster_types{$cluster_type} . ") found";
$state = "WARNING";
}
} # end scalar count
# if preferred master serial is not master
if ( $pri_serial && ( $pri_serial ne $curr_serial ) ) {
$string = $string . ", preferred master " . $pri_serial . " is not master!";
$state = "CRITICAL";
}
# Write an output string...
$string = $state . ": " . $curr_device . " (Master: " . $curr_serial . ", Slave: " . @help_serials[$#help_serials] . "): " . $string;
return ($state, $string);
} # end cluster state
sub get_vpn_state {
my $ipstunsdown = 0;
my $ipstuncount = 0;
my $ipstunsopen = 0;
my $ActiveSSL = 0;
my $ActiveSSLTunnel = 0;
my $string_errors = "";
my %entitystate = ( '1' => 'down', # Enumeration for the tunnel up/down states
'2' => 'up' );
$state = "OK";
# Unless specifically requesting IPSec checks only, do an SSL connection check
if ($vpnmode ne "ipsec"){
$ActiveSSL = get_snmp_value($session, $oid_ActiveSSL);
$ActiveSSLTunnel = get_snmp_value($session, $oid_ActiveSSLTunnel);
}
# Unless specifically requesting SSL checks only, do an IPSec tunnel check
if ($vpnmode ne "ssl"){
# Get just the top level tunnel data
my %tunnels = %{get_snmp_table($session, $oid_ipsectuntableroot . $oidf_tunndx)};
while (($oid, $value) = each (%tunnels)) {
#Bump the total tunnel count
$ipstuncount++;
#print "Tunnel name (" . $oid_ipsectuntableroot . $oidf_tunname . "." . $ipstuncount . ") is: " . get_snmp_value($session, $oid_ipsectuntableroot . $oidf_tunname . "." . $ipstuncount) . "\n";
#print "Tunnel status (" . $oid_ipsectuntableroot . $oidf_tunstatus . "." . $ipstuncount . ") is: " . get_snmp_value($session, $oid_ipsectuntableroot . $oidf_tunstatus . "." . $ipstuncount) . "\n";
#If the tunnel is up, bump the connected tunnel count
if ( $entitystate{get_snmp_value($session, $oid_ipsectuntableroot . $oidf_tunstatus . "." . $ipstuncount)} eq "up" )
{
$ipstunsopen++;
} else {
#Tunnel is down. Add it to the failed counter
$ipstunsdown++;
# If we're counting failures and/or monitoring, put together an output error string of the tunnel name and its status
if ($mode >= 1){
$string_errors .= ", ";
$string_errors .= get_snmp_value($session, $oid_ipsectuntableroot . $oidf_tunname . "." . $ipstuncount)." ".$entitystate{get_snmp_value($session, $oid_ipsectuntableroot . $oidf_tunstatus . "." . $ipstuncount)};
}
}
}
}
#Set Unitstate
my $unitstate="OK";
if (($mode >= 2 ) && ($vpnmode ne "ssl")) {
if ($ipstunsdown == 1) { $unitstate="WARNING"; }
if ($ipstunsdown >= 2) { $unitstate="CRITICAL"; }
}
# Write an output string...
$string = $unitstate . ": " . $curr_device . " (Master: " . $curr_serial .")";
if ($vpnmode ne "ipsec") {
#Add the SSL tunnel count
$string = $string . ": Active SSL-VPN Connections/Tunnels: " . $ActiveSSL."/".$ActiveSSLTunnel."";
}
if ($vpnmode ne "ssl") {
#Add the IPSec tunnel count and any errors....
$string = $string . ": IPSEC Tunnels: Configured/Active: " . $ipstuncount . "/" . $ipstunsopen. " " . $string_errors;
}
# Create performance data
$perf="|'ActiveSSL-VPN'=".$ActiveSSL." 'ActiveIPSEC'=".$ipstunsopen;
$string = $string.$perf;
# Check to see if the output string contains either "unkw", "WARNING" or "down", and set an output state accordingly...
if($string =~/uknw/){
$state = "UNKNOWN";
}
if($string =~/WARNING/){
$state = "WARNING";
}
if($string =~/down/){
$state = "CRITICAL";
}
return ($state, $string);
} # end vpn state
sub close_snmp_session{
my $session = $_[0];
$session->close();
} # end close snmp session
sub get_snmp_value{
my $session = $_[0];
my $oid = $_[1];
my (%result) = %{get_snmp_request($session, $oid) or die ("SNMP service is not available on ".$ip) };
return $result{$oid};
} # end get snmp value
sub get_snmp_request{
my $session = $_[0];
my $oid = $_[1];
return $session->get_request($oid) || die ("SNMP service not responding");
} # end get snmp request
sub get_snmp_table{
my $session = $_[0];
my $oid = $_[1];
return $session->get_table(
-baseoid =>$oid
);
} # end get snmp table
sub parse_args
{
my $ip = "";
my $community = "public";
my $pri_serial = "";
my $reset_file = "";
my $type = "status";
my $warn = 80;
my $crit = 90;
my $slave = 0;
my $vpnmode = "both";
my $mode = 2;
my $help = 0;
pod2usage(-message => "UNKNOWN: No Arguments given", -exitval => 3, -verbose => 0) if ( !@ARGV );
GetOptions(
'host|H=s' => \$ip,
'type|T=s' => \$type,
'community|C:s' => \$community,
'serial|S:s' => \$pri_serial,
'vpnmode|V:s' => \$vpnmode,
'mode|M:s' => \$mode,
'warning|w:i' => \$warn,
'critical|c:i' => \$crit,
'slave|s:1' => \$slave,
'reset|R:1' => \$reset_file,
'help|?!' => \$help,
) or pod2usage(-exitval => 3, -verbose => 0);
pod2usage(-exitval => 3, -verbose => 2) if $help;
return ($ip, $community, $type, $warn, $crit, $slave, $pri_serial, $reset_file, $mode, $vpnmode);
}
__END__
=head1 NAME
Check Fortinet FortiGate Appliances
=head1 SYNOPSIS
=item S<check_fortigate.pl -H -C -T [-w|-c|-S|-s|-R|-M|-V|-?]>
Options:
-H --host STRING or IPADDRESS Check interface on the indicated host
-C --community STRING Community-String for SNMP
-T -- type STRING CPU, MEM, Ses, VPN, Cluster
-S --serial STRING Primary serial number
-s --slave get values of slave
-w --warning INTEGER Warning threshold, applies to cpu, mem, session.
-c --critical INTEGER Critical threshold, applies to cpu, mem, session.
-R --reset Resets ip file (cluster only)
-M --mode STRING Output-Mode: 0 => just print, 1 => print and show failed tunnel, 2 => critical
-V --vpnmode STRING VPN-Mode: both => IPSec & SSL/OpenVPN, ipsec => IPSec only, ssl => SSL/OpenVPN only
-? --help Returns full help text
=head1 OPTIONS
=over 8
=item B<-H--host>
STRING or IPADDRESS - Check interface on the indicated host.
=item B<-C|--community>
STRING - Community-String for SNMP
=item B<-T|--type>
STRING - CPU, MEM, Ses, VPN, Cluster
=item B<-S|--serial>
STRING - Primary serial number.
=item B<-s|--slave>
BOOL - Get values of slave
=item B<-w|--warning>
INTEGER - Warning threshold, applies to cpu, mem, session.
=item B<-c|--critical>
INTEGER - Critical threshold, applies to cpu, mem, session.
=item B<-R|--reset>
BOOL - Resets ip file (cluster only)
=item B<-M|--mode>
STRING - Output-Mode: 0 => just print, 1 => print and show failed tunnel, 2 => critical
=item B<-V|--vpnmode>
STRING - VPN-Mode: both => IPSec & SSL/OpenVPN, ipsec => IPSec only, ssl => SSL/OpenVPN only
=back
=head1 DESCRIPTION
This plugin checks Fortinet FortiGate devices via SNMP
=head2 From Web:
=item 1. Select Network -> Interface -> Local interface
=item 2. Administrative Access: Enable SNMP
=item 3. Select Config -> SNMP
=item 4. Enable SNMP, fill your details
=item 5. SNMP v1/v2c: Create new
=item 6. Configure for your needs, Traps are not required for this plugin!
=head2 From CLI:
config system interface
edit "internal"
set allowaccess ping https ssh snmp fgfm
next
end
config system snmp sysinfo
set description "DMZ1 FortiGate 300C"
set location "Room 404"
set conctact-info "BOFH"
set status enable
end
config system snmp community
edit 1
set events cpu-high mem-low fm-if-change
config hosts
edit 1
set interface "internal"
set ip %SNMP Client IP%
next
end
set name "public"
set trap-v1-status disable
set trap-v2c-status disable
next
end
Thats it!
=cut</pre>
<br />
<br />
Auf den Geräten muss natürlich SNMP aktiviert werden:<br />
<br />
Via Web: <br />
<ol style="text-align: left;">
<li>Network -> Interface -> Interface, welches auf SNMP lauschen soll, auswählen. Achtung, nicht auf das externe Interface freigeben!</li>
<li>Administrative Access: Häckchen bei SNMP setzen</li>
<li>Config -> SNMP auswählen</li>
<li>Häckchen bei SNMP</li>
<li>SNMP v1/v2c: Create new</li>
<li>Traps werden nicht benötigt, Rest kann nach eigenem Willen konfiguriert werden</li>
</ol>
Via CLI:<br />
<ol style="text-align: left;">
<li> Login via SSH oder Web-CLI</li>
</ol>
<br />
<pre> config system interface
edit "internal"
set allowaccess ping https ssh snmp fgfm
next
end
config system snmp sysinfo
set description "DMZ1 FortiGate 300C"
set location "Room 404"
set conctact-info "BOFH"
set status enable
end
config system snmp community
edit 1
set events cpu-high mem-low fm-if-change
config hosts
edit 1
set interface "internal"
set ip %SNMP Client IP%
next
end
set name "public"
set trap-v1-status disable
set trap-v2c-status disable
next
end
</pre>
<br />
Damit das Plugin auch schön in Nagios eingebunden werden kann, hier noch die commands.cfg.<br />
<br />
Achtung, ich nutze hier Host Variablen <a href="http://nagios.sourceforge.net/docs/3_0/customobjectvars.html">http://nagios.sourceforge.net/docs/3_0/customobjectvars.html</a> <br />
<br />
<h3 style="text-align: left;">
commands.cfg:</h3>
<pre>define command {
command_name check_fortigate_cpu
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T cpu
}
define command {
command_name check_fortigate_slave_cpu
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T cpu -s
}
define command {
command_name check_fortigate_mem
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T mem
}
define command {
command_name check_fortigate_slave_mem
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T mem -s
}
define command {
command_name check_fortigate_cluster
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T cluster
}
define command {
command_name check_fortigate_pri_cluster
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T cluster -S $ARG1$
}
define command {
command_name check_fortigate_ses
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T ses -w 250 -c 350
}
define command {
command_name check_fortigate_slave_ses
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T ses -s -w 250 -c 350
}
define command {
command_name check_fortigate_vpn
command_line $USER1$/check_fortigate.pl -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -T vpn -V $ARG1$ -M 0
}
</pre>
<br />
<br />
Die ganzen Sachen gibt es natürlich auch direkt zum Download über <a href="http://exchange.nagios.org/directory/Plugins/Hardware/Network-Gear/Fortinet/check_fortigate-2Epl/details" target="_blank">exchange.nagios.org</a> <br />
<br />
<br />
Bei Fragen bitte wie immer melden.<br />
<br />
<br />
<br />
Mal sehen, was die Recherche zu Juniper Plugins betrifft, ggf. wird der nächste Eintrag über dieses Thema sein :-)</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com11tag:blogger.com,1999:blog-8503045420193335974.post-45129254734229037602013-07-24T14:36:00.001+02:002013-07-24T14:37:23.784+02:00Wie löscht man sicher, effizient und automatisiert Daten<div dir="ltr" style="text-align: left;" trbidi="on">
Bei meiner neuen Stelle schnappt man auch viele Dinge nebenbei auf, die verbessert werden wollen.<br />
<br />
Ein Beispiel ist das sichere Löschen von Notebooks / PCs / Servern zum Leasing-Ende, damit auf keinen Fall sensible Daten das Unternehmen verlassen und später bei <a href="http://www.gulli.com/news/17238-ebay-festplatte-gekauft-patientendaten-inklusive-2011-09-30" target="_blank">Ebay</a> landen können.<br />
<br />
Bisher wurden die Geräte händisch mit einer DBAN (Darik's Boot and Nuke) CD einzeln gestartet und anschließend mit manueller Bestätigung gelöscht.<br />
Als Löschmethode kam dabei <a href="http://transition.usaid.gov/policy/ads/500/d522022m.pdf" target="_blank">DoD 5220.22-M</a> Full zum Einsatz<br />
<br />
Kurzer Exkurs zu DBAN: <br />
DBAN unterstützt natürlich noch mehr Methoden:<br />
<ul style="text-align: left;">
<li>Quick Erase: 1x mit "0" überschreiben, eigentlich nur bei Virenbefall empfehlenswert</li>
<li>RCMP TSSIT OPS-II: 8x mit Zufallswerten überschreiben, geht allerdings</li>
<li><a href="http://transition.usaid.gov/policy/ads/500/d522022m.pdf" target="_blank">DoD Short (5220.22-M)</a>: Schritt 1 (mit "0" überschreiben), 2 (mit "1" überschreiben) und 7 (mit "Zufalls"werten überschreiben) des "vollen" DoD 5220.22-M </li>
<li><a href="http://transition.usaid.gov/policy/ads/500/d522022m.pdf" target="_blank">DoD Full (5220.22-M)</a>: 7x überschreiben</li>
<li>Gutmann: 35x Durchläufe (http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html), wobei der Erfinder mittlerweile selbst gesagt, dass diese Variante über das Ziel hinaus schießt. </li>
<li>PRNG: Pseudo Random Number Generator, wie der Name sagt, wird die Festplatte mit "Zufalls"-zahlen (bei heutigen Rechenwerke gibt es keine echte Zufälligkeit) überschrieben. Die Anzahl der Durchläufe kann angegeben werden.</li>
</ul>
Meine Empfehlung geht bei weniger sensiblen Daten zu DoD Short / PRNG mit 2-3 Durchläufen und bei sensibleren Daten zu DoD Full / PRNG 4-6 Durchläufe.<br />
<br />
Je nach Auswahl der Löschmethode und Größe der Festplatten kann das Löschen der Geräte lange dauern, aber was tut man nicht alles für das sichere Löschen der Daten.<br />
<br />
<br />
Um die Löschmethode effizienter durchzuführen, habe ich die Idee gehabt, einfach einen PXE-Server mit automatischem Löschen aufzusetzen, dieser soll komplett von der restlichen Netzwerk-Infrastruktur getrennt sein, theoretisch wäre es natürlich möglich den PXE-Server auf bestimmte MAC-Adressen einzuschränken, das führt aber in meinem Fall nicht ans Ziel.<br />
<br />
<br />
Dazu wird im ersten Schritt ein Ubuntu 12.04 Server installiert, es reicht dabei eine minimale Installation, z.B. auf Oracle VirtualBox oder auf kleiner, energieeffizienter Hardware wie z.B. Raspberry Pi.<br />
<br />
Nach erfolgter Installation loggt man sich via SSH oder Lokal auf dem System ein und installiert die nötigen Dienste via apt-get.<br />
<br />
<pre class="brush: bash;"># paketquellen erneuern
apt-get update
# Installation tftpd-hpa, isc-dhcp-server, syslinux, wget (optional, wenn dban via winscp
# übertragen wird)
apt-get install tftpd-hpa isc-dhcp-server syslinux wget
# stoppen des dhcp-server Dienstes
service isc-dhcp-server stop
# stoppen des tftpd-hpa Dienstes
service tftpd-hpa stop</pre>
<br />
<br />
Da nun die Dienste soweit installiert sind, geht es an die Konfiguration eben dieser, dazu werden die entsprechenden Konfiguration mit dem Lieblingseditor geöffnet und bearbeitet.<br />
<br />
vim /etc/dhcp/dhcpd.conf (absolute minimal Konfiguration):<br />
<pre>default-lease-time 600;
max-lease-time 7200;
authoritative;
log-facility local7;
# Achtung: idealerweise wird ein Netz genommen, welches noch nicht vorhanden ist
# Die Netzmaske muss entsprechend der maximal möglichen PXE-Clients gewählt werden,
# bei mir reicht ein /24 vollkommen aus
subnet 192.168.220.0 netmask 255.255.255.0 {
range 192.168.220.5 192.168.220.240;
# hier kommt die eigene IP, also des PXE-Servers
next-server 192.168.220.1;
# pre boot loader, kommen wir später zu
filename "/pxelinux.0";
}</pre>
<br />
Die Konfiguration des tftpd-hpa ist, Stand Juli 2013, für unsere Zwecke ausreichend und kann dementsprechend im Standard gelassen werden, ggf. kann die Listen-Address (/etc/default/tftpd-hpa) noch auf <br />
<br />
Nun beginnen die Vorbereitungen für das DBAN PXE-Image, dazu wird das Image von www.dban.org via wget oder lokal heruntergeladen und auf den Server, z.B. unter /usr/src, abgelegt und gemountet.<br />
<br />
<pre class="brush: bash;"># Download DBAN
wget -O /usr/src/dban-2.2.27.iso "http://downloads.sourceforge.net/project/dban/dban/dban-2.2.7/dban-2.2.7_i586.iso?r=http%3A%2F%2Fwww.dban.org%2Fdownload&ts=1374667513&use_mirror=surfnet"
# Mount der CD
mount -o loop /usr/src/dban-2.2.27.iso /mnt
# Kopieren der dban Dateien in das TFTP Verzeichnis
cp -r /mnt/* /var/lib/tftpboot
</pre>
<br />
Anschließend brauchen wir noch ein Pre-Boot Environment, dazu bedienen wir uns bei syslinux:
<br />
<pre class="brush: bash;"># Kopieren
cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
# preboot cfg
mkdir /var/lib/tftpboot/pxelinux.cfg
# einfügen der Konfiguration
echo "DEFAULT autonuke"
LABEL autodban
KERNEL dban.bzi
APPEND nuke="dwipe --autonuke --method dod522022m" silent
" > /var/lib/tftpboot/pxelinux.cfg/default
</pre>
<br />
Damit haben wir nun alle nötigen Schritte vorbereitet.<br />
<br />
Da ich relativ paranoid bin, habe ich das automatische Starten des DHCP-Servers deaktiviert, dadurch wird man gezwungen den DHCP-Server manuell und dadurch bewusst zu starten.<br />
Wichtig: seit Upstart muss man dieses allerdings an zwei Stellen tun!<br />
<pre bash="" brush:="" class=""># deaktiviere init.d dhcp-server beim boot
update-rc -f isc-dhcp-server remove
# deaktivere upstart dhcp-server beim boot
echo "manual" > /etc/init/isc-dhcp-server.override
# starte tftpd-hpa beim boot
update-rc.d tftpd-hpa defaults
</pre>
<br />
Damit der DHCP-Server gestartet werden kann, muss noch die IP-Konfiguration angepasst werden, dazu wird die Datei /etc/network/interfaces mit dem Lieblingseditor geöffnet und eine statische IP eingetragen werden:<br />
<pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.220.1
netmask 255.255.255.0
</pre>
<br />
Nach einem Reboot haben wir nun alle nötigen Arbeiten erledigt und können das automatische Löschen durch Starten des DHCP-Servers beginnen.<br />
<br />
<b><span style="color: red;">Aber Achtung, verbindet das System niemals, mit gestartetem DHCP-Server, mit dem lokalen LAN, denn der neue DHCP-Server könnte schneller als die anderen DHCP-Server antworten und das Telefon würde anschließend wohl nicht mehr still stehen ;-) </span></b>
<br />
<br />
Bei Fragen bitte einfach melden!
</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-44243312914264683272013-07-15T09:42:00.001+02:002013-09-17T10:32:39.063+02:00Wie überwache ich Oracle Datenbanken auf Schwellenwerte<div dir="ltr" style="text-align: left;" trbidi="on">
Da wir auf Oracle für unsere Applikationen einsetzen, sollen diese natürlich auch überwacht werden.<br />
<br />
Das geht relativ einfach mit SQL-Querys, benötigt wird dazu der Oracle Instant Client:<br />
<ul style="text-align: left;">
<li>x64: <a href="http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html">http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html</a></li>
<li>x86: <a href="http://www.oracle.com/technetwork/topics/linuxsoft-082809.html">http://www.oracle.com/technetwork/topics/linuxsoft-082809.html</a></li>
</ul>
Da ich ein Fan von Automatisierung bin, habe ich für die Installation unter Ubuntu 12.04 (Debian sollte ebenfalls funktionieren, für CentOS/Oracle/Rehadt muss nur das Umwandeln der RPM Pakete auskommentiert werden) ein Skript erstellt.<br />
<br />
Das Skript nutzt in der aktuellen Version eine Art Deploymentserver um die RPM Pakete abzuholen, mit geringem Aufwand kann man aber die Aufrufe von wget auch gegen ein cp o.ä. austauschen. <br />
Vor der Nutzung müssen noch die entsprechenden Variablen angepasst werden:<br />
<ul style="text-align: left;">
<li>Optional: proxy server</li>
<li>IP des Deployment Servers</li>
</ul>
Zusätzlich gibt es noch Abfragen ob der Instant Client mit PHP (interessant für Abfragen mittels PHP-Skripte) oder ohne und in x64 oder x86 installiert werden soll. <br />
<br />
Hier das Skript als Download: <a href="https://dl.dropboxusercontent.com/u/9482545/prepare_ora_instant.sh" target="_blank">prepare_ora_inst.sh </a><br />
<br />
<br />
<pre class="brush: bash;">#!/bin/bash
# Author: oliver.skibbe (at) gmail.com
# Purpose: install oracle instant client
# Date: 2013-05-21 15:00
# Variables
SRC=/usr/src
# deployment server, oracle instant client rpms should be there
deploymentserver="deploymentip/dns"
# http / https
http_type="http"
# basic auth
auth="user:password"
# proxy server for pecl/apt
proxy=""
# oracle versions
major=11.2
minor=0.3.0-1
# ora files
files=('basic' 'devel' 'sqlplus')
echo "####################################################"
echo -e "#### Oracle Instant Client Version $major.$minor ####"
echo "####################################################"
echo "Do you want to install 64-bit or 32-bit oracle instant client? 1/2"
read answer
case "$answer" in
1)
arch=x86_64
shortarch=64
;;
2)
arch=i386
shortarch=
;;
*)
echo "Wrong answer..try again"
exit 1
esac
echo "Do you want to install php extension? y/N"
read phpanswer
case "$phpanswer" in
y*|Y*)
echo "Installing php extension"
php=true
;;
*)
echo "Not installing php extension"
php=false
esac
if [ "x$proxy" = "x" ]; then
echo "Adding proxy to apt.conf"
if [ -d /etc/apt/apt.conf.d/ ] ; then
echo "Acquire::http::Proxy \"$proxy\";" >> /etc/apt/apt.conf.d/99proxy.conf
else
echo "Acquire::http::Proxy \"$proxy\";" >> /etc/apt/apt.conf
fi
# refresh sources
apt-get update
# install rpm to deb converter
apt-get install alien libaio1
for file in ${files[@]}
do
filename=oracle-instantclient$major-$file-$major.$minor.$arch.rpm
wget -c --no-proxy -O $SRC/$filename $http_type://$auth@$deploymentserver/deployment/global/oracle/$filename
if [ $? != 0 ] ; then
echo "Downloading $filename from $http_type://$deploymentserver/deployment/global/oracle/ failed!"
exit 1
fi
alien -i $SRC/$filename
done
# libs
echo "/usr/lib/oracle/$major/client$shortarch/lib" > /etc/ld.so.conf.d/oracle.conf
ldconfig
ORACLE_HOME=/usr/lib/oracle/$major/client$shortarch
# log directory
mkdir /usr/include/oracle/$major/client$shortarch/log
# includes
ln -s /usr/include/oracle/$major/client$shortarch $ORACLE_HOME/include
# path variables
cat << EOT > /etc/profile.d/oracle.sh
export ORACLE_HOME=$ORACLE_HOME
export PATH=\$PATH:\$ORACLE_HOME/bin
EOT
chmod +x /etc/profile.d/oracle.sh
if [ $php = true ] ; then
echo "php oracle stuff"
export ORACLE_HOME=$ORACLE_HOME
if [ "x$proxy" = "x" ]; then
pear config-set http_proxy $proxy
fi
pecl install oci8
echo "extension=oci8.so" > /etc/php5/apache2/conf.d/oci8.ini
service apache2 reload
fi
exit 0</pre>
<br />
<br />
Nach dem Ausführen des Skripts sollte die Installation des Oracle Instant Clients erfolgreich erledigt sein, anschließend kümmern wir uns nun um den Abfrageteil:<br />
<br />
Hier das Beispiel-Skript als Download: <a href="https://dl.dropboxusercontent.com/u/9482545/check_oracle_abfrage.php" target="_blank">check_oracle_abfrage.php</a> (Username, Password, IP/DNS, DBName und die Abfrage müssen noch angepasst werden!)<br />
<br />
<pre class="brush: php;">#!/usr/bin/php
<?php
// oracle database
$oracleuser = "user";
$oraclepass = "pass";
$instance = "ip/dbname";
$warn = $argv[1];
$crit = $argv[2];
// connect oracle database
$conn = oci_connect($oracleuser,$oraclepass,$instance);
$query = "select count(*) from table where export_date is null";
$abfrage = oci_parse($conn,$query);
oci_execute($abfrage);
$row = oci_fetch_array ($abfrage, OCI_BOTH);
$count = $row[0];
if ( $count >= $crit ) {
$exitCode = 2;
$exitString = "CRITICAL";
} else if ( $count >= $warn ) {
$exitCode = 1;
$exitString = "WARNING";
} else {
$exitCode = 0;
$exitString = "OK";
}
$perfData = "auftraege=$count;$warn;$crit";
// return values
echo $exitString . " {$count} Auftraege|" . $perfData;
exit($exitCode);
?></pre>
<br />
<br />
Das Skript muss nun noch ausführbar gemacht (chmod +x) oder direkt via php aufgerufen werden.<br />
<br />
Anschließend solltet ihr ein funktionierendes Oracle Abfragesystem haben.<br />
<br />
<br />
Bei Fragen bitte einfach melden.</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0tag:blogger.com,1999:blog-8503045420193335974.post-32072623775796548692013-07-15T09:04:00.001+02:002014-09-29T14:14:28.627+02:00Meine entwickelten Nagios Plugins<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
Da ich sehr viel im Bereich Monitoring, speziell Nagios und Icinga, unterwegs bin, habe ich natürlich mit der Zeit auch einige Plugins selbst geschrieben oder auch andere Plugins nach meinen Vorstellungen, Anforderungen überarbeitet bzw. Funktionen nachgerüstet.<br />
<br />
Meine eigenen Plugins sind meist in PHP oder Bash geschrieben, die überarbeiteten Plugins sind in PHP, Perl, Powershell, Python etc. geschrieben.<br />
<br />
Die meisten davon gibt es zum freien Download bei <a href="http://exchange.nagios.org/">http://exchange.nagios.org</a><br />
<br />
Diese Plugins will ich hier kurz vorstellen:<br />
<br />
Eigenentwicklungen:<br />
<ul style="text-align: left;">
<li><a href="http://exchange.nagios.org/directory/Plugins/Telephony/check_beronet/details" target="_blank">check_beronet</a> (geschrieben in PHP)<br />Überprüft die hervorragenden VoIP Gateways (ISDN,FXS/FXO,PRI zu SIP) der deutschen Marke Beronet (<a href="http://www.beronet.com/">http://www.beronet.com</a>)</li>
<ul>
<li>Fehler der Ports (inkl. Performance Daten)</li>
<li>Status des Links</li>
<li>Gesamt Anrufe + durchschnittliche Zeit pro Gespräch (inkl. Performance Daten)</li>
<li> Momentane Anrufe (inkl. Performance Daten)</li>
<li>Auslastung der Box/Karte (inkl. Performance Daten)</li>
<li>Systeminformationen: Revision, Firmware, Seriennummer</li>
<li>Uptime</li>
</ul>
</ul>
<ul style="text-align: left;">
<li><a href="http://exchange.nagios.org/directory/Plugins/Hardware/Environmental/Check-All4xxx/details" target="_blank">check_all4xxx</a> (geschrieben in PHP) <br />Überprüft <a href="http://www.allnet.de/home-automation-steuer-computer.html?&tx_mmallnetproductplugin_pi1[showUid]=546275" target="_blank">Sensorboxen</a> [ALL4000/ALL4500] der deutschen Marke <a href="http://www.allnet.de/" target="_blank">Allnet </a>auf Schwellenwerte (z.B. Temperatur, Luftfeuchtigkeit, Rauchsensor, Lichtsensor, ...) und gibt diese inkl. Performance Daten zurück. <br />Die Sensoren werden über Zahlenwerte ausgewählt.</li>
<li><a href="http://exchange.nagios.org/directory/Plugins/Helpdesk-and-Ticketing/check_otrs_tickets-2Ephp/details" target="_blank">check_otrs_tickets.php</a> (geschrieben in PHP) <br />Eines meiner weiteren Lieblingsprodukte, <a href="http://www.otrs.org/" target="_blank">OTRS</a> das führende Open-Source Ticket-Request System. <br />Dieses Plugin überprüft eine konfigurierte OTRS Datenbank auf eine Menge an Tickets. Damit es flexibel ist, können die IDs der entsprechenden States und Queues über einen Parameter abgefragt und konfiguriert werden. Liefert ebenfalls Performance Daten zurück.</li>
<li><a href="http://exchange.nagios.org/directory/Plugins/Reporting/check_file_count-2Esh/details" target="_blank">check_file_count.sh</a> (geschrieben in BASH)<br />Überprüft einen Pfad auf eine konfigurierbare Menge an Dateien und gibt die älteste Datei zurück (im Anwendungsfall gibt es einen Spooler, der manchmal nicht aufräumt..), inkl. Performance Daten.<i><b></b></i></li>
<li><a href="https://dl.dropboxusercontent.com/u/9482545/check_file_count.ps1" target="_blank">check_file_count.ps1</a> (geschrieben in Powershell)<br />Das selbe Plugin, nur für Windows. Überprüft einen Pfad auf eine konfigurierbare Menge an Dateien, inkl. Performance Daten.<i><b></b></i></li>
</ul>
Überarbeitete/übernommene Plugins:<br />
<ul style="text-align: left;">
<li><a href="http://exchange.nagios.org/directory/Plugins/Hardware/Printers/check_printer--2D-All-in-one-printer-check-suitable-for-most-devices/details" target="_blank">check_printer</a> (geschrieben in PHP) - hinzugefügt/überarbeitet: Performance Daten, zusätzliche Drucker, snmp v2c, snmp v3 vorbereitet, Bug-Fixes<br />Dieses Plugin fragt die gängigsten Drucker mit SNMP 1/v2c und später mit SNMP Version 3 ab</li>
<ul>
<li>counter - z.B. Menge an bisherig gedruckten Seiten, inkl. Performance Daten</li>
<li>toner/Ink - liefert den Füllstand des Toners oder der Tinte zurück, inkl. Performance Daten</li>
<li>paper - liefert den Füllstand der Papiertrays zurück (jedes tray kann separat abgefragt werden!), inkl. Performance Daten</li>
<li>hardware - gibt Hardware-Daten (z.B. CPU) zurück</li>
<li>parts - gibt den Zustand bestimmter Bauteile zurück</li>
<li>alerts - gibt Ereignisse zurück, unwichtige Ereignisse werden soweit ignoriert</li>
<li>accounting - gibt den Status einer vorher konfigurierten Kostenstelle zurück</li>
</ul>
</ul>
</div>
<ul style="text-align: left;">
<li><a href="http://exchange.nagios.org/directory/Plugins/Hardware/UPS/APC/UPS-Checks/details" target="_blank">check_ups</a> (geschrieben in PERL) - hinzugefügt/überarbeitet check_APC: Schwellenwerte, Verbleibende Zeit auf Batterie, Ausgabe, Bug-Fixes<br />Dieses Plugin fragt die gängigen USVen ab</li>
<ul>
<li>Globaler Status</li>
<li>UPS/USV Type</li>
<li>Batteriekapazität</li>
<li>Leistung in %</li>
<li>Temperatur</li>
<li>Leistung in Wh</li>
<li>Verbleibende Zeit auf Batterie</li>
<li>Seriennummer, Herstellungsdatum (informativ..), Firmware-Version</li>
</ul>
</ul>
<br />
Das sind natürlich nicht alle, aber schon mal eine gewisse Auswahl, vielleicht hilft es dem einen oder anderen mal.<br />
<br />
Falls jemand Interesse, Ideen für neue Plugins oder Änderungen an bestehenden Plugins hat, bitte einfach kurz melden.</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com6tag:blogger.com,1999:blog-8503045420193335974.post-5627090949648727402013-07-11T10:05:00.003+02:002013-07-11T10:28:43.736+02:00Wie ändert man den Hostnamen bei einem Ferrari OfficeMaster Gateway<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Da unsere Ferrari OfficeMaster Gateways regelmäßig aussteigen und anschließend das Log das Ferrari Messaging Server fluten, habe ich das Logging Ziel auf einen anderen Host umgestellt, der mehr Speicher und Auswertungsmöglichkeiten hat (Logstash + ElasticSearch + Graylog2)<br />
<br />
Da die Hostnamen der OMGs aber nicht wirklich eindeutig sind und ich keine bessere Möglichkeit gefunden habe, den Hostnamen anderweitig zu ändern, habe ich mich per SSH mit der Box verbunden und die Skripte durchforstet.<br />
<br />
Dabei habe ich folgende Stelle in /etc/init.d/omg.setup gefunden:<br />
<br />
<br />
<pre class="brush:bash;"># Perhaps hostname defined by user
if [ -e /data/hostname ] ; then
hn=$(</data/hostname)
hostname ${hostnamepar} ${hn}
echo "export HOSTNAME=${hn}" >>/tmp/cmdline
fi</pre>
<br />
<br />
Aus diesem Ausschnitt geht hervor, dass man einfach nur den Hostnamen in /data/hostname ablegen muss, folgender Befehl nimmt einem das ab:<br />
<br />
<pre class="brush:bash;">echo "HOSTNAME" > /data/hostname
</pre>
</div>
<br />
Anschließend muss die Box neugestartet werden, damit die Änderungen aktiv werden.</div>
Oliver Skibbehttp://www.blogger.com/profile/15828774323175630823noreply@blogger.com0