Alle Beiträge von adlerweb

Microsoft SQL Server: Zugangsdaten wiederherstellen

Wer ein System verwalten will benötigt ein passendes Administrationspasswort. Dumm, wenn das System von nicht mehr erreichbaren Dritten eingerichtet wurde und keine brauchbare Dokumentation existiert. So  geschehen bei einem System mit Microsoft SQL Server, zu welchem kein sa-Passwort vorlag und die Windows-Zugänge offenbar gesperrt wurden.

Falls es nicht ohnehin klar ist: All diese Schritte solltet ihr natürlich nur an Systemen durchführen, welche euch gehören bzw. in nur nach (schriftlicher) Absprache mit dem Besitzer. Wer sich an fremden Systemen vergeht bekommt Probleme  mit der jeweiligen Staatsanwaltschaft und/oder dem zuständigen Admin und die möchtet ihr beide nicht kennen lernen ;).

Erster Anlaufpunkt: Windows-Logins. Üblicherweise sollten lokale Windows-Administratoren immer Administrationszugang zum SQL-Server haben. Hierzu einfach als lokaler Admin anmelden und im SQL Management Studio (oder der jeweils anderen Managementsoftware) die Windows-Authentifizierung nutzen.
Bild: https://www.adlerweb.info/blog/wp-content/uploads/2016/05/sql1-300×226.png

Hat der vorherige Admin die Windows-Zugänge herausoperiert muss man etwas tiefer eingreifen:

  1. Stoppt alle Dienste und beendet alle Clients, welche den Datenbankserver nutzen
  2. Öffnet den „Sql Server Configuration Manager“
  3. Stoppt unter „SQL Server-Dienste“ alle laufenden Dienste
    Bild: https://www.adlerweb.info/blog/wp-content/uploads/2016/05/sql2-300×53.png
  4. Doppelklick auf den Dienst SQL Server (nicht Agent oder Browser) um die Einstellungen zu öffnen
  5. Unter „Erweitert“ findet sich der Punkt „Startparameter“. Diesen durch Doppelklick editierbar machen. Am Anfang der Zeile „-m;“ einfügen
    Bild: https://www.adlerweb.info/blog/wp-content/uploads/2016/05/sqlfix-300×62.png
    Hintergrund: Mit -m wird der Server in den „single user maintenance mode“ geschaltet. Hierbei können Windows-Admins eine Verbindung zum Server aufbauen, es ist jedoch nur eine Sitzung zulässig. Sollte sich also ein anderes Programm verbinden ist kein Zugriff zur Verwaltung mehr möglich.
  6. Einstellungsfenster schließen und nur den SQL Server-Dienst wieder Starten
  7. Eine Eingabeaufforderung/cmd mit Administrationsrechten starten und per sqlcmd mit dem Server verbinden. Da der Server-Browser gestoppt ist müssen die Serverdaten manuell angegeben werden:
    sqlcmd -E -S tcp:localhost\INSTANZNAME
  8. Nun erstellen wir uns einen entsprechenden Zugang zum Server. Ich verwende den lokalen Systemadministrator, es ist jedoch auch möglich andere Nutzer, auch z.B. aus einer Domäne, so hinzuzufügen
    create login [SERVERNAME\Administrator] from windows;
    EXEC sp_addsrvrolemember 'SERVERNAME\Administrator','sysadmin';
    GO;
  9. Sollte der Befehl ohne Fehlermeldungen abschließen ist der Nutzer eingerichtet. Das sqlcmd-Fenster kann geschlossen werden
  10. Um den Wartungsmodus abzuschalten stoppen wir im Sql Server Configuration Manager den Serverdienst, gehen wieder wie zuvor in die Eigenschaften und entfernen das „-m;“ wieder aus den Startparametern
  11. Zuletzt werden alle zuvor aktiven SQL-Serverdienste wieder gestartet. Da an den bestehenden Logins keine Änderung vorgenommen wurde sollten Clients und Dienste unverändert wieder funktionieren. Zusätzlich sollte der angegebene Nutzer nun über Windows-Authentifizierung volle Administrationsrechte auf den Server besitzen.

Getestet mit 2008R3, sollte aber auch mit allen anderen zwischen 2005 und 2016 funktionieren.

Now fail already! Wenn der Browser über Umwege XOrg lahmlegt

Ugh. Schon wieder. Das Rattern in der Ecke hat meist eine recht konstante Ursache: Die CPU meines Laptops läuft auf 100% und sorgt für ordentliche Lüfterdrehzahlen. Gehen wir mal auf Ursachensuche:

Bei CPU-Last ist erster Anlaufpunkt natürlich top/htop. In meinem Fall aber leider nicht sehr Hilfreich: Xorg sei der Verursacher. Weites Feld. Aus meiner Erfahrung geht dann der Blick erst mal auf die laufenden Programme. Nicht selten hat sich auf einer geöffneten Webseite eine Flash-Werbung, ein HTML5-Video oder sonstige zappelnde Dinge mit Nervfaktor versteckt und bringen das Rendering in Gang. Leider konnte ich dieses mal nichts finden. Auch der interne Taskmanager von Google Chrome zeigt – anders als in solchen Fällen üblich – keine auffällig hohen Lasten. Um sicher zu gehen halte ich per SIGSTOP alle UI-Programme kurz an – keine Änderung. Es ist also mit hoher Wahrscheinlichkeit keine Grafikausgabe, welche die Probleme auslöst.

Zurück zum Start. Wir wissen, dass Xorg die Last bringt, allerdings vermutlich nicht im Grafikbereich. Schauen wir uns top nochmal genauer an. Die Browser sind noch in SIGSTOP und entsprechend verschwunden. Hinter XOrg macht sich nun dbus breit. Dbus? Kurze Lastspitzen OK, aber Dauerlast? Ein Blick mit dbus-monitor bringt eine Wall-of-log zum Vorschein:

method call time=1462212788.744495 sender=:1.1259306 -> destination=org.freedesktop.DBus serial=6 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=RemoveMatch
   string "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',arg0='org.gtk.vfs.Daemon'"
method return time=1462212788.744507 sender=org.freedesktop.DBus -> destination=:1.1259306 serial=6 reply_serial=6
method call time=1462212788.744535 sender=:1.1259306 -> destination=org.freedesktop.DBus serial=7 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',arg0='org.gtk.vfs.Daemon'"
method return time=1462212788.744544 sender=org.freedesktop.DBus -> destination=:1.1259306 serial=7 reply_serial=7
method call time=1462212788.744600 sender=:1.1259306 -> destination=org.freedesktop.DBus serial=8 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=StartServiceByName
   string "org.gtk.vfs.Daemon"
   uint32 0
method return time=1462212788.744611 sender=org.freedesktop.DBus -> destination=:1.1259306 serial=8 reply_serial=8
   uint32 2
method call time=1462212788.744748 sender=:1.1259306 -> destination=org.freedesktop.DBus serial=9 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetNameOwner
   string "org.gtk.vfs.Daemon"
method return time=1462212788.744761 sender=org.freedesktop.DBus -> destination=:1.1259306 serial=9 reply_serial=9
   string ":1.1258771"
method call time=1462212788.744895 sender=:1.1259306 -> destination=:1.1258771 serial=10 path=/org/gtk/vfs/mounttracker; interface=org.gtk.vfs.MountTracker; member=LookupMount
   struct {
      array of bytes "/NAME@DOMAIN.org" + \0
      array [
         dict entry(
            string "query"
            variant                array of bytes "subject=blabla&body=blabla" + \0
         )
         dict entry(
            string "type"
            variant                array of bytes "mailto" + \0
         )
      ]
   }
error time=1462212788.745079 sender=:1.1258771 -> destination=:1.1259306 error_name=org.gtk.GDBus.UnmappedGError.Quark._g_2dio_2derror_2dquark.Code15 reply_serial=10
   string "Der angegebene Ort wird nicht unterstützt"

…und das in Endlosschleife. Uhm, ja. mailto? Das sind üblicherweise Links in Webseiten oder Dokumenten um E-Mails zu versenden. Stimmt, ich hatte vor einigen Stunden auf einer Webseite einen Mail-Link angeklickt. Ohne Reaktion.

Offenbar hat sich die DE an eben diesem Maillink festgefressen. „Der angegebene Ort wird nicht unterstützt“. Kein Wunder, denn in den „Standardprogrammen“ ist für E-Mails nichts hinterlegt. Anstatt das Ganze aber einfach als Fehlschlag einzuordnen und abzubrechen wird die Aktion in Endlossschleife ständig wiederholt. Da auch Xorg an Dbus hängt (und offenbar nicht sonderlich effizient auf dessen Events reagiert) geht auch dieser in die Knie. Da ich auf die Schnelle keine Möglichkeit fand das dbus-event rauszuwerfen musste ein Dummy-Mailprogramm hinhalten. Event geht rein, Returncode kommt, Dbus gibt Ruhe. Warum nicht gleich so?

Ranttime #10 – Übertriebene Usability: FreeDownloadManager

Der FreeDownloadManager war immer meine Software der Wahl wenn es darum ging unter Windows größere Mengen an Dateien aus dem Internet zu laden. Mit der neuen Version hat man aber „die Usability verbessert“. Oder anders gesagt: Alle Funktionen entfernt um die Oberfläche Idiotensicher zu machen.

PHP: Binärdaten als Float interpretieren

Aktuell arbeite ich daran Binärdaten einer Steuerung für ein Logging-System zu übersetzen. Die Daten werden – mit verschiedenen Formaten – per TCP angeliefert und kommen in etwas ungewöhnlichen Formaten (MSB/LSB, Füllbits, etc) herein. Die erste Aufgabe meines Scriptes besteht entsprechend darin die Daten in Binärform aufzubereiten. Das meiste sind ASCII-Werte, welche per chr() schnell übersetzt sind. Auch das Zusammensetzen von vorzeichenlosen Integern ist mit etwas Shiften kein Problem.

Gegen die Wand lief ich dann allerdings bei Kommawerten. Zwar nutzt sowohl die Steuerung als auch PHP Gleitkommazahlen nach IEEE754, allerdings lässt sich PHP mit dem üblichen Type-juggling/casting nicht dazu überreden die Binärdaten als Float zu interpretieren. Die Lösung fand sich (wie üblich) auf Stackoverflow: pack/unpack.

$input = 0xbf9e0419;
var_dump(unpack('f', pack('i', $input)));

Und schon weiß auch PHP, dass 0xbf9e0419 eine -1.2345 ist. Commence logging.

Script: Automatisches LetsEncrypt-Renewal

In BitBastelei #178 hatte ich schon das Anfordern von Zertifikaten über LetsEncrypt gezeigt. Leider konnte ich bisher keine vernünftige Möglichkeit finden Zertifikaten automatisch erneuern zu können. Glücklicherweise hilft hier ein Bash-Script von Stefan Beckers weiter: Es sucht die installierten Zertifikate, prüft welche bald ablaufen und erneuert diese. Guter Startpunkt, aber nicht ganz für meine Anforderungen geeignet: Im Script wird letsencrypt-auto verwendet, welches in meinem System nicht installiert ist. Auch die Syntax des Clients scheint sich geändert zu haben. Weiterhin ist das Script stark auf Debian fixiert.

Etwas Bash-Foo selbst ist alles auf meine Bedürfnisse angepasst: Pfade & Binaries lassen sich einfacher ändern, die Syntax ist aktuell wieder lauffähig und es lässt sich pro Domain angeben welche Dienste bei einem Renew neu gestartet werden müssen. Nicht groß getestet, bisher scheinen aber noch keine Katzen geplatzt zu sein. Vielleicht hifts ja…

[nvidia/qt5/kdenlive] Segfault on various KDE-software using NVIDIA 361.16

Uhm crap. The last system update just pulled a new beta version of NVIDIAs binary driver. Usually not that much of a deal, I went for testing due to a bug in their stable driver some years ago and never ran into a problem. Well, at least until now.  This time the testing-curse found its way into my system and I found myself no longer able to start my video editor kdenlive. Segmentation Fault. I suspected my setup first since I am running a rather unusual multihead configuration but could also with just one monitor I ran into the same problem. Well, looks like I have to dig deeper. Some gdb later at least a clue:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff0b640c5 in XScreenCount (dpy=0x0) at Macros.c:109
109	int XScreenCount(Display *dpy) { return (ScreenCount(dpy)); }
(gdb) bt
#0  0x00007ffff0b640c5 in XScreenCount (dpy=0x0) at Macros.c:109
#1  0x00007fffea7f50da in glXGetClientString () from /usr/lib/libGLX.so.0
#2  0x00007ffff7fed3b3 in ?? () from /usr/lib/qt/plugins/xcbglintegrations/libqxcb-glx-integration.so
#3  0x00007ffff7fed5b1 in ?? () from /usr/lib/qt/plugins/xcbglintegrations/libqxcb-glx-integration.so
#4  0x00007ffff686fc7b in QSGRenderLoop::instance() () from /usr/lib/libQt5Quick.so.5
#5  0x00007ffff68a19e5 in QQuickWindowPrivate::init(QQuickWindow*, QQuickRenderControl*) () from /usr/lib/libQt5Quick.so.5
#6  0x00007ffff694b68d in QQuickView::QQuickView(QWindow*) () from /usr/lib/libQt5Quick.so.5
#7  0x00000000006bd190 in ?? ()
#8  0x00000000006c3d7b in ?? ()
#9  0x00000000007af3cc in ?? ()
#10 0x000000000046346b in ?? ()
#11 0x00007ffff188e610 in __libc_start_main () from /usr/lib/libc.so.6
#12 0x0000000000463949 in _start ()

So XScreenCount or libGLX is the suspect. In my case GLX is provided by NVIDIAs binary driver (nouveau had limited multihead support last time I checked). Also some QT5-stuff is mentioned in the backtrace.

A bit of search engine voodoo later it turns out NVIDIA already acknowledged the problem. Aaron Plattner writes:

I reproduced the problem and tracked it down to this buggy code in Qt5’s qxcbglxintegration.cpp:

static bool vendorChecked = false;
    static bool glxPbufferUsable = true;
    if (!vendorChecked) {
        vendorChecked = true;
        const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR);
        if (glxvendor && !strcmp(glxvendor, "ATI"))
            glxPbufferUsable = false;
    }

When this code is called during sddm-greeter startup, there’s no current GLX context, so this gets called with a NULL argument.

While here SDDM is not the problem I think kdenlive, which uses similar libraries, runs into the same problem. He also pushed a corresponding patch to NVIDIAs GIT-repository. Sadly the current HEAD is not 100% ABI compatible with the official driver release. Also I really didn’t want to get into my distributions xorg-packaging-foo. Ultimately I reverted to the current NVIDIA stable version 358.16 to get back into business. So – lesson confirmed: Beta releases can fix problems or cause problems. But who doesn’t like a bit of stability-gambling, right?

MySQL: Wuchernde Log-Dateien (mysqld-bin.xxx) zähmen

Je nach Konfiguration können MySQL-Server bei vielen Anfragen die Festplatte mit Binärdateien des Namens mysqld-bin.(zahl) füllen. Hintergrund: In diesen Dateien zeichnet der Server alle Anfragen auf, welche den Datenbestand verändern (also INSERT, UPDATE, etc). Das kann z.B. zur Datenrettung bei Abstürzen oder zur Replikation bei der Verwendung mehrerer Server hilfreich sein. Hat man jedoch nur beschränkt Speicherplatz zur Verfügung können diese Dateien zum Problem werden.

Log einmalig löschen

Benötigt man nur einmalig den Speicherplatz kann man sich mit einem passenden MySQL-Befehl behelfen. Hierzu schaut man sich die durchnummerierten Log-Dateien an und überlegt sich einen Zeitpunkt, der als neuen Startpunkt dienen soll. Transaktionen vor diesem Zeitpunkt können bei Ausfällen ggf. Beschädigt werden, daher empfielt es sich einen Zeitpunkt zu wählen, der kurz vor dem letzten Backup liegt. Der Befehl lautet dann z.B.:

PURGE BINARY LOGS BEFORE '2015-12-08 12:34:56';

Log abschalten

Duch Abschaltung der Log-Funktion ist das Problem schnell und dauerhaft behoben, allerdings verliert man die Möglichkeit mehrere Server zu verwenden und kann unter Umständen bei Ausfällen (Absturz, Stromausfall, etc) Daten verlieren. Zum Abschalten öffnet man die Konfigurationsdatei im Editor seiner Wahl – diese findet sich üblicherweise unter /etc/mysql/my.cnf oder /etc/my.cnf. Im Abschnitt [mysqld] sollte ein Eintrag „log-bin“ zu finden sein, eventuell noch mit einer Zahl oder einem Dateinamen dahinter. Diesen inaktiviert man durch Vorstellen eines Raute-Zeichens:

[mysqld]
...
#log-bin

Nachdem der MySQL-Server neu gestartet wurde legt er keine weiteren Dateien an. Alte Einträge müssen ggf. wie weiter oben beschrieben entfernt werden.

Loggröße einschränken

Ein guter Mittelweg ist es meist Logs anzulegen, um alle damit verbundenen Optionen nutzen zu können, das Alter jedoch zu beschränken. Ich mache täglich eine Sicherung, damit ist sichergestellt, dass ich Daten mit >24h nicht aus dem Log widerherstellen muss. Um bei Störungen des Backup jedoch etwas Puffer zu erhalten lasse ich Logs 3 Tage stehen. Hierzu nutzt man die oben beschriebene Konfigurationsdatei und sucht im Abschnitt [mysqld] nach dem Eintrag „expire_logs_days“. Ist er vorhanden kann er passend modifiziert werden, andernfalls fügt man die Zeile in der Nähe von log-bin ein. Um Logs nach 3 Tagen zu löschen lautet die Konfiguration:

[mysqld]
...
log-bin
expire_logs_days = 3

Nach einem Neustart des MySQL-Servers werden ältere Logs automatisch gelöscht, zukünftig werden sie nur noch 3 Tage aufbewahrt.

Durch die Änderung konnte ich „mal schnell“ mehr als 10GB an alten Logs vom betroffenen Server kratzen – bei einem embedded-System mit 16GB Speicher nicht grade unerheblich.

Gentoo dev-lang/yasm-1.2.0-r1: Segfault während compile

Narf? Segfault bei der Gentoo-Grundinstallation? Unschön. Verursacher ist dev-lang/yasm-1.2.0-r1, welches irgendwo als dependency gezogen wurde. Der Code ist dabei nicht sehr hilfreich:

built perfect hash table of size 512
./re2c -b -o gas-token.c ./modules/parsers/gas/gas-token.re
./re2c -b -o nasm-token.c ./modules/parsers/nasm/nasm-token.re
Makefile:4780: recipe for target 'gas-token.c' failed
make: *** [gas-token.c] Segmentation fault
make: *** Deleting file 'gas-token.c'
make: *** Waiting for unfinished jobs....
Makefile:4783: recipe for target 'nasm-token.c' failed
make: *** [nasm-token.c] Segmentation fault
make: *** Deleting file 'nasm-token.c'

Auch dmesg macht nicht viel schlauer:

[*] re2c[*]: segfault at 0 ip 00007f3cc90441d0 sp 00007fffaa8fdee0 error 4 in libc-2.20.so[7f3cc8fda000+18e000]
[*] re2c[*]: segfault at 0 ip 00007ff5681921d0 sp 00007ffccd9b4300 error 4 in libc-2.20.so[7ff568128000+18e000]

Libc sollte funktionieren, alle anderen Pakete zeigten keine Fehler, aber zur Sicherheit mal neu kompilieren: Keine Änderung. Auch mein Versuch die als unstable markierte Version dev-lang/yasm-1.3.0 zu verwenden wirft die gleiche Meldung. Müssen wir wohl tiefer rein.

Erster Schritt: Handarbeit. Im passenden Ordner unter /var/tmp/Portage führe ich make selbst aus – kein Fehler. Schlecht, denn ein Fehler den man nicht reproduzieren kann, kann man auch nur schwer beheben. Also anderer Weg: In /usr/portage/dev-lang/yasm finden sich die passenden ebuilds – mit ebuild *1.2.0* compile lässt sich der Vorgang starten, mit anderen Befehlen am Ende auch selektiv einzelne Schritte durchführen. Treffer, hier tritt der Fehler auch auf. Nachdem spielen mit der make.conf (Stichwort CFLAGS, USE, …) keine Bessung zeigte bleibt dann nur ein Blick ins Innere. re2c wird aus eigenen Quellen gebaut und ist nicht mit dev-util/re2c verbunden. Ich nenne nach einem fehlgeschlagenen Compile die re2c-Binary um und lege unter selben Namen ein Script an, welches die original-Binary mit strace zur Fehlersuche aufruft:

#!/bin/bash
strace ./re2c.org $*

Ergebnis:

open("/tmp/tmpfuxtE34", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 EACCES (Permission denied)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
+++ killed by SIGSEGV +++
./re2c: line 2:  6931 Segmentation fault      strace ./re2c.org $*

Also hat es mit /tmp zu tun? Die Datei existiert nicht, schreibrechte sollte der Prozess auch haben. /tmp ist auf dem System nicht speziell eingerichtet, es liegt auf der root mit ext4 und rw,relatime,data=ordered. Auf anderen Systemen, welche keine Probleme haben, liegt es im RAM. Ist eventuell ext4 und dessen Funktionsumfang das Problem? Also schnell ein mount -t tmpfs -o noexec,nosuid tmp /tmp hinterher und nochmal versucht – fehlerfrei. Vermutlich fehlt in ext4 eine Dateioperation oder irgendwo kracht es beim asynchronen Betrieb zwischen löschen und neu erstellen. Warum es ohne portage/ebuild funktioniert ist dann immer noch die Frage. Wie auch immer: tmpfs stand ohnehin noch auf der Todo-Liste, worksforme.

ArchLinux: Update sperrt root-Login per SSH

Ouch – nicht schön. Nach dem Update einer remote-Kiste war der Login per SSH nicht mehr möglich. Schuld ist offenbar eine Änderung der SSH-Defaults: Während bisher der root-Login auch ohne explizite Angabe in der Konfiguration erlaubt war, muss dies nun in der Konfiguration mit einem PermitRootLogin yes manuell zugelassen werden. Sofern kein anderes Konto besteht heißt das nach einem Update dann: KVM oder Remote-Hands müssen her um den Eintrag zu setzen und den Server so wieder verwaltbar zu machen. Ein Hinweis vorab wäre natürlich einfacher gewesen :/.

Edit: Zu früh gemault: Im Announcement der OpenSSH-Leute ist die Änderung beschrieben, RTFM hätte also geholfen…

Potentially-incompatible Changes

[…]
* The default for the sshd_config(5) PermitRootLogin option has
changed from „yes“ to „prohibit-password“.

Arduino: boolean vs. byte

Möchte man einen einfachen Status im an/aus-Format notieren ist üblicherweise ein Boolean der Dateityp der Wahl. Technisch gesehen unterstützt der bei Arduino verwendete ATMega jedoch immer nur 8-Bit-Register, sodass auch ein Boolean (1-Bit-Wert) intern meist als Byte (8-Bit-Wert) abgespeichert wird. Klingt nicht sehr effizient, aber kann man per Hand tatsächlich „besser“ arbeiten?

Gehen wir von einem einfachen Beispiel aus: Wir möchten mehrere dieser Zustände speichern und auf deren Basis eine Entscheidung treffen. Für dieses Beispiel wird der Wert immer invertiert – in diesem Fall könnte man es auch kompakter Lösen, aber da es nur als Platzhalter für komplexeren Code gilt lasse ich das mal so stehen. Alle Beispiele sind Auszüge eines größeren Programms, die absoluten Größen also ohne weitere Aussagekraft.

Erster Versuch: Mit Boolean

boolean dir1 = false;
boolean dir2 = false;
boolean dir3 = false;
//[...]
if(dir1) {
  //Aktionen
  dir1 = false;
}else{
  dir1 = true;
}

//23.644 Byte Flash, 1.537 Byte RAM

Zum Vergleich mit einem einzigen „byte“-Wert, dessen einzelne Bits als Informationsspeicher verwendet werden sollen:

byte dir = 0x00;
//[...]
if(dir & 0x01) {
  //Aktionen
  bitSet(dir, 0x01);
}else{
  bitClear(dir, 0x01);
}

//23.650 Byte Flash, 1.535 Byte RAM

Schaut man auf das eigentliche Programm gewinnt die Variante mit Boolean – 6 Byte kleiner. Nicht wirklich verwunderlich – hat man ein ganzes Byte müsste sich direkt ein Sprung bei !=0 durchführen lassen. Mit Byte-Teilen ist ein Vergleich oder ein vorheriges UND nötig, welches zusätzliche Befehle und somit auch Speicher und CPU-Takte verschlingt. Schaut man jedoch auf den RAM dreht sich das Bild: Hier ist das einzelne Byte sparsamer. 2 Byte kommen mir jedoch etwas klein vor – ich fürchte hier hat der Compiler mit seinen Optimierungen einiges der boolean-Logik geschmissen, denn theoretisch sollte zur ersten Variante deutlich mehr Abstand sein.

Wie auch immer: Selbst ohne große Analyse zeigt sich, was ich schon erwartet hatte: Boolean spart Flash, Byte spart RAM. Welche Variante die sinnvollere ist hängt letztendlich vom jeweiligen Projekt ab. Da mir der RAM ausging war die Umstellung auf Byte eine gute Möglichkeit etwas zu sparen. Möglicherweise hätte es auch gereicht den Compiler nicht mit -Os anzuweisen, einen möglichst kleinen Code zu generieren.