Kategorie: Technik

Windows-Hintergrundbild mit Perl setzen

· · 0 Kommentare

Das Setzen des Windows-Hintergrundbilds ist von Perl aus ganz einfach - zumindest wenn man die Win32-API verwendet:

use strict;
use warnings;
use Win32::API;

use constant SPI_SETDESKWALLPAPER => 0x0014;
use constant SPIF_UPDATEINIFILE   => 0x0001;
use constant SPIF_SENDCHANGE      => 0x0002;
use constant ZERO                 => 0x0000;

my $syspinf = Win32::API->new('user32', 'SystemParametersInfo', [I,I,P,I], I) or die "SystemParametersInfo not available.\n";

$syspinf->Call(SPI_SETDESKWALLPAPER, ZERO, $ARGV[0], SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

Das Skript erwartet den Namen des Bildes inklusive Pfad als Parameter.


inotifywait bricht bei Dateiänderungen ab

· · 0 Kommentare

Es gibt verschiedene Strategien, wie die Änderung einer Datei gespeichert werden kann. Die beiden i.d.R. eingesetzten Verfahren sind entweder die vorhandene Datei mit dem neuen Inhalt zu überschreiben oder aber den geänderten Inhalt in eine neue Datei zu speichern und dann die Dateien auszutauschen.

Unter Sicherheitsaspekten ist der Dateiaustausch klar vorzuziehen, denn erst wenn der neue Inhalt erfolgreich in die neue Datei gespeichert wurde, wird die bisherige Datei gelöscht. Beim direkten Überschreiben kann entweder beim Zugriff durch andere Programme eine halbfertige Datei geliefert werden oder es kommt durch Hardware- / Software-Fehler zu einer Situation, in welcher der alte Inhalt bereits zerstört, der neue Inhalt aber nicht erfolgreich geschrieben werden kann.

Dies hat Auswirkungen auf die Möglichkeiten, mittels inotifywait auf Dateiänderungen zu reagieren. Während beim direkten Überschreiben inotifywait ordnungsgemäß eine Änderung der Datei registriert, bricht inotifywait beim Dateiaustausch ab - die z.B. im Beitrag "Sass ohne Ruby" geschilderte Vorgehensweise scheitert dann, da die ursprünglich überwachte Datei ja nicht mehr existiert.

$ while inotifywait -e close_write style.scss; do sassc --style compact style.scss style.css ; done

Eine Möglichkeit, dies zum umgehen, ist das Überwachen des kompletten Verzeichnisses mit Abfrage der geänderten Datei

inotifywait -e close_write,moved_to,create -m . |
while read -r directory events filename; do
	if [ "$filename" = "style.scss" ]; then
		sassc --style compact style.scss .style.css
	fi
done

was aber - je nach Anzahl der im Verzeichnis vorhandenen Dateien und deren Änderungshäufigkeit - zu einer erhöhten Systemlast führen kann.


WSUS-Updates remote genehmigen

· · 0 Kommentare

Soll das Skript, welches die WSUS-Updates genehmigt (oder ablehnt) nicht auf dem WSUS-Server selbst sondern auf einem anderen Server ausgeführt werden, scheitert dies zunächst mit der Fehlermeldung

Der Typ [Microsoft.UpdateServices.Administration.AdminProxy] wurde nicht gefunden.

Grund ist das Fehlen der benötigten Powershell-Cmdlets, welche zur Ausführung installiert werden müssen. Eine Suche im Internet führt meist in die falsche Richtung, nämlich zu Installationsanleitungen für die WSUS 3.0 SP2 Administration Console, welche aber für den unter Server 2019 verwendeten WSUS schon ein paar Tage zu alt ist.

Die benötigten Module lassen sich über den "Assistent zum Hinzufügen von Rollen und Features" installieren, hier ist unter "Features" der Punkt "Remoteserver-Verwaltungstools" / "Rollenverwaltungstools" / "Windows Server Upgrade Service-Tools" / "API- und PowerShell-Cmdlets" zu wählen.

Als letztes muß in dem Skript nur noch eine Zeile zum Zugriff auf den Remote-Server angepasst werden:

$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($serverName, $useSecureConnection, $portNumber)

Der Aufruf der Funktion "getUpdateServer" wird um die drei selbsterklärenden Parameter "$serverName", "$useSecureConnection" sowie "$portNumber" erweitert.


Virtualisierung unter Debian

· · 0 Kommentare

Wird auf Windows-Clients oft VirtualBox als Desktop-Virtualisierungslösung eigesetzt, stellt man nach dem Wechsel auf Debian fest, daß VirtualBox seit Buster nicht mehr in den Paketquellen enthalten ist.

Das Debian-Wiki empfieht als Ersatzlösung das auf QEMU/KVM basierende Paket virt-manager, welches in den "normalen" Paketquellen enthalten ist und somit einfach installiert werden kann:

$ sudo apt install virt-manager

Nach dem ersten Aufruf poppt erst einmal ein Fenster "System policy prevents management of local virtualized systems" zur Eingabe des Kennwortes hoch. Wer dies vermeiden möchte, kann seinen Benutzer der Gruppe "libvirt" hinzufügen:

$ sudo usermod -aG libvirt $(whoami)

Anschließend kann eine virtuelle Maschine aufgesetzt (und verwendet) werden.

Netzwerkbrücke

Je nach Anwendungsszenario stellt man sehr schnell fest, daß zwar die virtuelle Maschine ohne Probleme überall ins Netz kommunizieren kann, eine Kommunikation vom Host zur virtuellen Maschine hingegen nicht möglich ist.

Um dies zu ermöglichen, muß eine virtuelle Netzwerkbrücke eingerichtet werden. Hierzu schlagen die meisten per Suchmaschinen auffindbaren Lösungsmöglichkeiten vor, den Network-Manager zu deaktivieren und die Konfiguration der Netzwerkinterfaces komplett von Hand zu übernehmen, aber es funktioniert auch mittels Network-Manager, und das sogar recht einfach und elegant.

Zuerst einmal gilt es, die aktuelle Netzwerkverbindung sowie das verwendete Interface auszulesen, das in der Spalte "DEVICE" zu finden ist.

$ sudo nmcli connection show
NAME                         UUID  TYPE      DEVICE
Kabelgebundene Verbindung 1  ****  ethernet  enp3s0

Als nächstes wird die Brücke hinzugefügt, das Spanning Tree Protocol wird hierbei nicht benötigt.

$ sudo nmcli connection add type bridge ifname br0 stp no
Verbindung »bridge-br0« (****) erfolgreich hinzugefügt.

Die bestehende Netzwerkverbindung wird dann als Slave zur Brücke hinzugefügt, hierbei ist "enp3s0" durch das im ersten Schritt ermittelte Device zu ersetzen:

$ sudo nmcli connection add type bridge-slave ifname enp3s0 master br0
Verbindung »bridge-slave-enp3s0« (****) erfolgreich hinzugefügt

Wirft man einen Blick auf die nun vorhandenen Verbindungen, so werden neben der ursprünglichen Verbindung auch die beiden neuen Einträge angezeigt:

$ sudo nmcli connection show
NAME                         UUID  TYPE      DEVICE
Kabelgebundene Verbindung 1  ****  ethernet  enp3s0
bridge-br0                   ****  bridge    br0
bridge-slave-enp3s0          ****  ethernet  --

Als letzte Schritte folgen das Deaktivieren der bisherigen Verbindung und das Aktivieren der Netzwerkbrücke:

$ sudo nmcli connection down "Kabelgebundene Verbindung 1"
Verbindung »Kabelgebundene Verbindung 1« wurde erfolgreich deaktiviert (aktiver D-Bus-Pfad: /org/freedesktop/NetworkManager/ActiveConnection/3)

$ sudo nmcli connection up bridge-br0
Verbindung wurde erfolgreich aktiviert (master waiting for slaves) (Aktiver D-Bus-Pfad: /org/freedesktop/NetworkManager/ActiveConnection/6)

Ein abschließender Blick auf die Verbindungen zeigt, daß die Umschaltung erfolgreich war:

$ sudo nmcli connection show
NAME                         UUID  TYPE      DEVICE
bridge-br0                   ****  bridge    br0
bridge-slave-enp3s0          ****  ethernet  enp3s0
Kabelgebundene Verbindung 1  ****  ethernet  --

Die so erzeugte Brücke kann dann in virt-manager für die Netzwerkverbindungen der virtuellen Maschinen verwendet werden:

Im entsprechenden Dialog ist aber eine Stolperfalle eingebaut: Im Feld "Brückenname" muß nicht der von nmcli ausgegebene NAME, sondern das DEVICE angegeben werden.


Hinweis auf veraltete Beiträge

· · 0 Kommentare

Problematisch bei Beiträgen zu Technik ist, daß sie meist ein Verfallsdatum haben. Was heute prima funktionert, kann bereits in der nächsten Softwareversion entweder an ganz anderer Stelle versteckt sein oder wurde komplett gestichen. So häufen sich auch hier im Blog die Kommentare von Lesern, die übersehen, daß ein mit "Windows 7" gekennzeichneter Beitrag unter Windows 10 wohl nur noch durch Zufall so nachvollziehbar sein wird.

Aus diesem Grund wird nach und nach in älteren Beiträgen ein entsprechender Hinweistext eingebaut. Um nicht die Beitragstexte selbst ändern zu müssen, wird dies über ein paar Zeilen Code in der "functions.php" realisiert:

function outdated_notification($content) {

	global $post;

	if (is_single()) {
		$isOutdated = get_post_meta(get_the_ID(), 'veraltet', true);
		if ($isOutdated) {
			$content = '<p class="outdated_notification">Der Inhalt ist veraltet!</p>' . $content;
		}
	}
	return $content;
}

add_filter('the_content', 'outdated_notification');

Der Code richtet einen WordPress-Filter ein, der jedesmal, wenn der Inhalt eines Beitrags über die Funktion "the_content" angefragt wird, den Beitragsinhalt vor Verwendung durch die Funktion "outdated_notification" schickt.

Diese prüft zuerst, ob es sich um eine Einzeldarstellung des Beitrags handelt ("is_single()") und im Erfolgsfall, ob für den Beitrag das Feld "veraltet" gesetzt wurde. Ist dies der Fall, wird ein HTML-Paragraph mit einem Hinweistext vor den Beginn des eigentlichen Beitragsinhalts gestellt.

Der oben skizzierte Code funktionert allerdings nur, solange der Inhalt über die Funktion "the_content" angefragt wird. Wird vom gewählten Thema hingegen die Funktion "get_the_content" verwendet, ist etwas mehr Bastelarbeit notwendig, denn hier sind keine Filter vorgesehen.