WSL Instanz Backup

Ein Beschreibung wie eine Sicherheitskopie einer WSL Umgebung erstellt wird und wie, umgekehrt, aus dieser Sicherheitkopie wieder ein System erstellt wird.

Auflisten der aktuellen WSL-Instanzen

CMD > wsl --list
Windows-Subsystem für Linux-Distributionen:
Ubuntu-20.04 (Standard)
rancher-desktop
rancher-desktop-data
CMD >

Sicherung/Backup einer WSL-Instanz erstellen

wsl --export Ubuntu-20.04 C:\tmp\ubu20.04.tar

Löschen einer WSL-Instanz vom Recher

Wenn die WSL-Instanz nicht mehr benötigt wird, kann sie gelöscht werden. Eines Sicherheitkopie wurde ja, siehe oben, erstellt.

CMD > wsl --terminate  Ubuntu-20.04
CMD > wsl --unregister Ubuntu-20.04

Wiederherstellen einer WSL-Instanz

CMD > wsl --import Ubuntu-20.04 C:\Users\ProgIsArt\AppData\Local\Packages\Ubuntu C:\tmp\ubu20.04.tar

Ergänzende Maßnahmen

Ändern des Default-Users

Nach dem wieder einspielen des Backup hatte ich das Problem, dass ich immer root gewesen bin. Hat mich erst mal nicht gestört, funktioniert dann aber nicht mehr mit der Rancher Desktop Integration. Mit folgendem Befehl wechselt man wieder den Default User.

  • Erstelle, wenn noch nicht vorhanden, /etc/wsl.conf mit folgendem Inhalt

[user]
default=progisart

Anschließend terminiere die Instanz und starte sie neu

Probleme mit Rancher-Desktokp (Docker)

Wenn das Backup zurück gespielt wird habe ich anschließend Probleme mit der Docker-Integration gehabt.

docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.35/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

Diesen Fehler kann man beheben indem man folgenden Befehl aufruft.

sudo setfacl --modify user:progisart:rw /var/run/docker.sock

WSL Kommando Referenz

Basic commands

## -----------------------------------------------------------------------------
## Liste verfügbarer Distro's ...
wsl --list --online

## -----------------------------------------------------------------------------
## Installieren einer konkreten Distro ...
wsl --install -d Ubuntu-22.04

## -----------------------------------------------------------------------------
## Version der Distro anzeigen ...
wsl --list -v
  NAME                    STATE           VERSION
* Ubuntu-K8s              Stopped         2

Sammlung hilfreicher Linux Befehle

Hier eine Sammlung hilfreicher Kommandos. Dies ist eine vorlaufende Liste, es werden also immer mal wieder neuen Befehle dazu kommen.

Disk Usage

[root@progIsArt /]# du -h --max-depth 3 | sort -hr  | head -n 20
294M    .
192M    ./usr
93M     ./var
82M     ./usr/lib64
67M     ./var/cache/yum
67M     ./var/cache
40M     ./usr/bin
38M     ./usr/share
29M     ./usr/lib64/python2.7
27M     ./var/lib
25M     ./usr/lib
23M     ./var/lib/rpm
9.5M    ./usr/share/i18n
9.2M    ./usr/lib/systemd
9.2M    ./etc
9.0M    ./usr/share/cracklib
7.4M    ./usr/sbin
7.3M    ./usr/lib64/gconv
6.5M    ./etc/udev
5.7M    ./usr/lib/udev

Zahlen konvertieren

numfmt

[root@progIsArt var]# numfmt --to=iec 1000
1000
[root@progIsArt var]# numfmt --to=iec 1024
1.0K
[root@progIsArt var]# numfmt --to=iec 2000
2.0K
[root@progIsArt var]# numfmt --to=iec 2048
2.0K
[root@progIsArt var]# numfmt --to=iec 3000
3.0K
[root@progIsArt var]# numfmt --to=iec 10000000000000000
8.9P
[root@progIsArt var]# numfmt --to=iec 10000000000000000000000000000000000000000000000000000
numfmt: value too large to be converted: '10000000000000000000000000000000000000000000000000000'

String to number

[root@progIsArt /]# if [          "0" == 0 ];  then echo ">> ${?}"; else echo "## ${?}"; fi;
>> 0
[root@progIsArt /]# if [     "$((0))" == 0 ];  then echo ">> ${?}"; else echo "## ${?}"; fi;
>> 0
[root@progIsArt /]# if [ "((2 + 1))"  == 3 ];  then echo ">> ${?}"; else echo "## ${?}"; fi;
## 1
[root@progIsArt /]# if [ "$((2 + 1))" == 3 ];  then echo ">> ${?}"; else echo "## ${?}"; fi;
>> 0

[root@progIsArt /]# a=""
[root@progIsArt /]# echo "${a} $((${a}))"
 0
[root@progIsArt /]# a="0"
[root@progIsArt /]# echo "${a} $((${a}))"
0 0
[root@progIsArt /]# a="5"
[root@progIsArt /]# echo "${a} $((${a}))"
5 5
[root@progIsArt /]# unset a
[root@progIsArt /]# echo "${a} $((${a}))"
 0

String Manipulationen

## SED distinguishes between groups. They can also be replaced.
[root@progIsArt /]# echo 'huhuhahahihi' | sed -E 's/(huhu)(haha)(hihi)/##&##\1hoho\3/g'
##huhuhahahihi##huhuhohohihi

## Delete line 1-3 from output
[root@progIsArt /]# cat /etc/os-release | sed 1,3d
PRETTY_NAME="Alpine Linux v3.12"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"

Archivieren

[root@progIsArt /]# tar -czvf allShs.tgz -T <(find /etc /usr/libexec -type f | grep -E "*\.sh$")
tar: Removing leading `/' from member names
/etc/profile.d/colorgrep.sh
/etc/profile.d/colorls.sh
/usr/libexec/openldap/create-certdb.sh
/usr/libexec/grepconf.sh

[root@progIsArt /]# find /etc /usr/libexec -type f | grep -E "*\.sh$" | tar -czvf allShs.tgz -T -
tar: Removing leading `/' from member names
/etc/profile.d/colorgrep.sh
/etc/profile.d/colorls.sh
/usr/libexec/openldap/create-certdb.sh
/usr/libexec/grepconf.sh

[root@progIsArt /]# find /etc /usr/libexec -type f | grep -E "*\.sh$" | zip allShs.tgz -@
  adding: /etc/profile.d/colorgrep.sh (244 bytes security) (deflated 73%)
  adding: /etc/profile.d/colorls.sh (244 bytes security) (deflated 75%)
  adding: /usr/libexec/openldap/create-certdb.sh (244 bytes security) (deflated 73%)
  adding: /usr/libexec/grepconf.sh (244 bytes security) (deflated 73%)


## Split a very large file into multiple pieces and check the results during transfer
# 01: Some filesystems are unsorted, so that's why it looks so complicated.
# 02: ... verify the pieces by checkfile
# 03: combine the pieces again into a single file
# 04: check that source and result are identical.
[00::root@progIsArt /]# split -b 2M -d 'veryLargeFile.arc' 'veryLargeFile.arc.'
[01::root@progIsArt /]# echo -n >veryLargeFile.md5 && ls -1 | grep -F 'veryLargeFile.arc.' | sort -u | xargs -rI{} md5sum '{}' >>veryLargeFile.md5
[02::root@progIsArt /]# md5sum -c veryLargeFile.md5
[03::root@progIsArt /]# echo -n >veryLargeFile.arc2 ; ls -1 | grep -F 'veryLargeFile.arc.' | sort -u | xargs -rI{}  cat '{}' >>veryLargeFile.arc2
[04::root@progIsArt /]# md5sum veryLargeFile.arc veryLargeFile.arc2

## Create a patch and use it.
[root@progIsArt /]# diff -ruN OriginalDir UpdatedDir > PatchFile
# ...-p0  Apply the patch to the same directory structure as when the patch was created
[root@progIsArt /]# patch -p1 < PatchFile

## Create an password protected ZIP-Archive
[root@progIsArt /]# zip -re aDir.zip aDir/

## Download apt packages with all dependencies to local
[root@progIsArt /]# apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances docker-ce | grep "^\w" | sort -u)
Datei-Manipuplationen
## -----------------------------------------------------------------------------
## Remove all comments and blank lines from a file
[root@progIsArt /]# grep -Ev '^\s*+(#.*)?$' docker-compose.yml

Netzwerk

## Inspect local network
[root@progIsArt /]# nmap -v -sL $(ifconfig | grep inet | grep -v inet6 | grep -vF '127.0.0.1' | tr -s ' ' | cut -d ' ' -f 3 | cut -d '.' -f 1-3).0/24

Bilder

## Crop images with offset in batch convert
## ... -crop widthxheigth+xpos+ypos
[root@progIsArt /]# find ../from | sort -n | cut -d '/' -f 3 | xargs -I{} convert "../from/{}"  -crop 2500x750+210+270 "{}"

SSH

to test: docker-twins

## SSH Auto Login
[helmi@progIsArt-helmi ~]$ ssh-keygen -t rsa
[helmi@progIsArt-helmi ~]$ ssh-copy-id -i .ssh/id_rsa.pub helmo@twin-helmo
[helmi@progIsArt-helmi ~]$ ssh helmo@twin-helmo
[helmo@progIsArt-helmo ~]$ whoami
helmo
[root@progIsArt-helmo .ssh]# touch authorized_keys
[root@progIsArt-helmo .ssh]# chmod 600 authorized_keys
[root@progIsArt-helmo .ssh]# cat /home/helmo/.ssh/authorized_keys  | grep helmi >> authorized_keys
[helmi@progIsArt-helmi ~]$ ssh root@twin-helmo
Last login: Fri Mar 12 07:14:42 2021 from docker-twins_twin-helmi_1.docker-twins_default
[root@progIsArt-helmo ~]# whoami
root

# Add specific SSL cert to agent.
[root@progIsArt /]# eval "$(ssh-agent -s)"  ## .. only importent on mingw git-bash
[root@progIsArt /]# ssh-add ~/.ssh/id_yourprivate_cert

Apt Update

#!/bin/bash
apt-get update -y
apt-get upgrade -y
#apt-get dist-upgrade -y
apt-get autoclean -y
apt-get clean -y
apt-get autoremove -y

Beispiele

Ich kann jetzt nicht alles erklären, aber hier sind ein paar Beispiele. Es sind Beispiele für Konvertierungen, Schleifen, Parameter usw. Nicht für effiziente Programmierung. Vieles von den Ergebnisses bekommt man einfacher hin.

alias findMaxHumanReadable='function _findMaxHumanReadable(){
  limit=$(( ${1} ))

  maxSize=-1;

  du | sort -nr | sed -E "s/\s/ /g" | while read -r line; do
    currentSize=$(echo "${line}" | cut -d " " -f 1)
    if [ ${maxSize} == -1 ]; then maxSize=${currentSize}; fi
    if (( ${currentSize} < $((maxSize * ${limit} / 100)) )); then break; fi

    _size=$(numfmt --to=iec ${currentSize})
    _fileName=$(echo "${line}" | cut -d " " -f 2)

    echo -e "${_size}\t${_fileName}"
  done
};_findMaxHumanReadable'

HTH
ProgIsArt

WSL2 und RDS

Hier einmal eine Beschreibung, wie die WSL2 so aufgesetzt werden kann, dass eine Remote Desktop Verbindung möglich ist.

Installation des Ubunutu Desktop

Installation des Ubunutu Desktop, hier nur die minimal Konfiguration. Ohne --no-install-recommends nicht mit angibt, werden auch LibreOffice und andere unnötigen Komponenten installiert.

Installation des Ubunutu Desktop

sudo apt update && sudo apt -y upgrade
sudo apt-get install --no-install-recommends ubuntu-desktop

Installation des X-Servers

sudo apt-get install xrdp
sudo apt-get install xfce4
sudo apt-get install xfce4-goodies

Änderung der Konfiguration

sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/max_bpp=32/#max_bpp=32\nmax_bpp=128/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g' /etc/xrdp/xrdp.ini
echo xfce4-session > ~/.xsession

Editieren der Datei /etc/xrdp/startwm.sh
- comment these lines to:

    #test -x /etc/X11/Xsession && exec /etc/X11/Xsession
    #exec /bin/sh /etc/X11/Xsession
  • add these lines:

    # xfce
    startxfce4

Starten des X-Servers

Starten des X-Servers. Muss nach jedem Neustart wiederholt werden

sudo /etc/init.d/xrdp start

RDP Skalierung an High-DPI Display Win10

Vor kurzem habe ich hier im Blog beschrieben, wie man unter WSL2 den Remote Desktop Service einrichtet. Das funktioniert auch alles ganz gut, allerdings bekommt man mit der Auflösung Probleme, wenn man an einem 4K Monitor sitzt und die Anzeige skaliert (125%/200%). Was eigentlich immer der Fall ist, weil man ja sonst nicht erkennen kann.

Der Remote Desktop Client nimmt diese Skalierung nicht mit. Somit hat Layer 8 dann Probleme mit dem Erkennen des Dargestellten.

Dies kann man unter Win10 zunächst einmal nicht so einfach ändern. Hier eine Beschreibung, wie man dann doch macht.

Erstelle eine mstsc.exe.manifest

Im Verzeichnis %SystemRoot%\System32\ befindet sich die mstsc.exe, die EXE für den Remote Desktop Client. Hier muss eine Datei mstsc.exe.manifest mit folgenden Inhalt erstellt werden.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide::PreferExternalManifest

Damit die Manifestdatei angezogen wird, muss noch die Registry bearbeitet werden:

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide

ein zusätzlicher Schlüssel angelegt werden

PreferExternalManifest
- DWORD (32-bit)

-   `decimal` value `1`

Einfach geht das über die Powershell Console

REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide" /v PreferExternalManifest /t REG_DWORD /d 1 /f

Größe eines DiskImage reduzieren

Das Image einer SD-Karte ist schnell erstellt. Aber wie reduziert man seine Größe, um es z.B. auf eine kleinere SD aufzuspielen oder es platzsparend zu lagern.

Nach langer Recherche habe ich nun endlich eine für mich mich praktikable Möglichkeit gefunden, die ich hier kurz vorstellen möchte.

Erstellen eines DiskImages

Zunächst müssen wir wissen, auf welches Device die SD Karte gemountet wird.

root@earthX200:~# cd /tmp
root@earthX200:~# ## Ohne SD Karte
root@earthX200:/tmp# lsblk >1
root@earthX200:~# ## Mit SD Karte
root@earthX200:/tmp# lsblk >2
root@earthX200:/tmp# diff 1 2
34a35,37
> mmcblk0               179:0    0  14,9G  1 disk
> ├─mmcblk0p1           179:1    0   256M  1 part  /media/progisart/boot
> └─mmcblk0p2           179:2    0  14,6G  1 part  /media/progisart/rootfs

Nun kann ein Image der SD Karte erstellt werden.

root@earthX200:~# dd bs=1MB if=/dev/mmcblk0 of=~/dockerpi.img  status=progress
15931000000 Bytes (16 GB, 15 GiB) kopiert, 837 s, 19,0 MB/s
15931+1 Datensätze ein
15931+1 Datensätze aus
15931539456 Bytes (16 GB, 15 GiB) kopiert, 837,434 s, 19,0 MB/s

Freiraum schaffen mit gParted

Bevor das Image mit gParted bearbeitet werden kann, muss es zunächst gemountet werden.

root@earthX200:~# udisksctl loop-setup -f dockerpi.img
Mapped file dockerpi.img as /dev/loop24.

gParted erkennt die Loop-Devices nicht automatisch. Wenn sie beim Öffnen aber explizit angegeben werden funktioniert es.

progisart@earthX200:~$ sudo gparted /dev/loop24
[sudo] Passwort für progisart:
GParted 1.0.0
configuration --enable-libparted-dmraid --enable-online-resize
libparted 3.3
gparted-UI

gparted-UI

Nun können die Partionen wie gewohnt mit gParted bearbeitet werden. Für das Beispiel wird die 2 Partion (/dev/loop24p2) verkleinert.

Wenn die Partitions-Bearbeitung abgeschlossen ist, nicht vergessen, dass Image wieder auszuwerfen bzw. zu unmounten.

root@earthX200:~# udisksctl loop-delete -b /dev/loop24

Neues, kleineres Image erstellen

Bisher hat sich nichts an der Größe des Images geändert. Es ist nur am Ende des Image ein nicht partitionierter Bereich entstanden.

Diese kann man sich auch anzeigen lassen, bzw. man kann sich das Ende des partionierten Bereiches anzeigen lassen.

root@earthX200:~# fdisk -l dockerpi.img
Festplatte dockerpi.img: 14,86 GiB, 15931539456 Bytes, 31116288 Sektoren
Einheiten: Sektoren von 1 * 512 = 512 Bytes
Sektorgröße (logisch/physikalisch): 512 Bytes / 512 Bytes
E/A-Größe (minimal/optimal): 512 Bytes / 512 Bytes
Festplattenbezeichnungstyp: dos
Festplattenbezeichner: 0x738a4d67

Gerät         Boot Anfang     Ende Sektoren Größe Kn Typ
dockerpi.img1        8192   532479   524288  256M  c W95 FAT32 (LBA)
dockerpi.img2      532480 13230079 12697600  6,1G 83 Linux

Die zwei wichtigen Daten sind > Einheiten: Sektoren von 1 * 512 = 512 Bytes
> …
> Gerät Boot Anfang Ende Sektoren Größe Kn Typ
> dockerpi.img1 8192 532479 524288 256M c W95 FAT32 (LBA)
> dockerpi.img2 532480 13230079 12697600 6,1G 83 Linux

Auf das Ende muss noch +1 drauf gerechnet werden und so kann nun mit dd ein neues, kleiners Image erstellt werden.

dd bs=512 count=13230080 if=~/dockerpi.img of=~/dockerpi_s.img status=progress

root@earthX200:~# dd bs=512 count=13230080 if=~/dockerpi.img of=~/dockerpi_s.img status=progress
6676411904 Bytes (6,7 GB, 6,2 GiB) kopiert, 72 s, 92,7 MB/s
13230080+0 Datensätze ein
13230080+0 Datensätze aus
6773800960 Bytes (6,8 GB, 6,3 GiB) kopiert, 72,916 s, 92,9 MB/s

Nicht vergessen, das Image kann nun zur weiteren Reduktion noch gepackt werden. Aber der schwierige Teil ist hiermit durch.

HTH
ProgIsArt

Add Swap to file

Meine letzte Linux-Installation unter UEFI-Restriktionen als Dual-Boot-System parallel zu Windows auf zwei unterschiedlichen Platten in einem Notebook war nicht ganz so einfach. Die Standard-Installation ist mit Ubuntu ja mittelerweile kein Ding mehr. Wird es dann aber spezieller, muss man höllisch aufpassen, nichts falsch zu machen. Insbesondere stellte mich mein Wunsch, dass Installationsmedium zu Verschlüsseln, vor eine Herausforderung.

Das Betriebssystem (`/' – EXT4) liegt auf der einer Partition, während SWAP für normal auf einer eigenen, anderen Partition liegt. Beide in einem verschlüsselten Bereich (LVM) unterzubringen, so wie es bei der Standardinstallation, war nicht möglich.

Allerdings ist mir wiederholt der Installer abgestürzt, vielleicht ist es also einfach nur ein Bug und wird zukünftig behoben (Ubu20.04).

Als Workaround habe ich den SWAP als Datei in der Hauptpartition untergebracht. Wie das geht beschreibe ich im Folgendem.

Anlegen einer Datei mit der entsprechenden Größe (12GB)

[root@progIsArt /]# dd if=/dev/zero of=/swapfile bs=1G count=12
[root@progIsArt /]# ls -lh | grep swapfile
-rw-r--r--   1 root root  12G Feb 21 12:04 swapfile

Datei soll nur für root zugreifbar sein

[root@progIsArt /]# chmod 600 /swapfile

Umwandeln der Datei zum SWAP

[root@progIsArt /]# mkswap /swapfile
[root@progIsArt /]# swapon /swapfile

FSTAB anpassen

[root@progIsArt /]# vi /etc/fstab
...
/swapfile                                 none            swap    sw              0       0
...

Check

[root@progIsArt /]# swapon --show

Netzwerkmasken

Allgemeines zu Netzwerkmasken und Basis für diesen Post: * Wikipedia - Netzwerkmaske

Was bei Wikipedia jedoch nicht drin steht: * Was bedeutet z.B. 192.168.178.1/20 (und warum ist es so eigentlich gar nicht richtig.)? * Wieso ist eine Netzwerkmaske 192.168.16.0/20 falsch?

Zunächste einmal eine IPv4 Netwerkmaske:

     1111 1111  1111 1111  1111 1111  1111 1111
       ^     ^    ^     ^    ^     ^    ^     ^
       |     |--[8]     |--[16]    |--[24]    |--[32]
       |          |          |          |
       |--[3]     |--[11]    |--[19]    |--[27]

Die auch übliche oder bekannte Schreibweise 255.255.255.255 meint also nichts anderes als 4x8 Bit.

Für das Verhalten was ich hier betrachten möchte verhalten sich /8 - /16 - /24 - /32 identisch, sie befinden sich nur in unterschiedlichen Segmenten auf der Adresse. Genau verhält es sich mit /3 - /11 - /19 - /27.

/27 zeigt auf das 3 Bit von vorne, die letzten 5 sind also frei. Mit diesen 5 hinteren Bits lässt sich max. 31 darstellen. Nennen wir es einmal die Schrittweite.

     1110 0000
       ^
       |--[27]

  0 .. 32 .. 64 .. 96 .. 128 .. 160 .. 192 .. 224 .. 256

somit sind mit einer /27 Netzwerkmaske am Ende folgen IP-Ranges richtig beschrieben:

  0/27  ==>    0- 31
 32/27  ==>   32- 63
 64/27  ==>   64- 95
 96/27  ==>   96-127
128/27  ==>  128-159
160/27  ==>  160-191
192/27  ==>  192-223
224/27  ==>  224-255

Damit wird dann auch klar, dass

112/27  ==>  96-127

formal zwar nicht falsch, von mehr Fachkenntnis jedoch zeugen würde, wenn

96/27  ==>  96-127

geschrieben würde.

Die Netzwerkmaske /28 ist noch feiner und meint dann folgende IP-Ranges:

  0 .. 16 .. 32 .. 48 .. 64 .. 80 .. 96 .. 112 .. 128 ..
  .. 144 .. 160 .. 176 .. 192 .. 208 .. 224 .. 240 .. 256

     1111 0000
        ^
        |--[28]

Praxistest

  192.168.178.8/29

  1111 1111
       ^
     => 111 = 7
      0-7
   *  8-15
     16-23
    ...

root@earthX200:~# nmap -sP -n 192.168.178.8/29
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-05 14:30 CEST
Stats: 0:00:00 elapsed; 0 hosts completed (0 up), 8 undergoing ARP Ping Scan
ARP Ping Scan Timing: About 56.25% done; ETC: 14:30 (0:00:00 remaining)
Nmap scan report for 192.168.178.11
Host is up (0.11s latency).
MAC Address: 52:D4:F6:61:74:A6 (Unknown)
Nmap scan report for 192.168.178.12
Host is up (0.12s latency).
MAC Address: 6A:FF:7A:28:93:CA (Unknown)
Nmap done: 8 IP addresses (2 hosts up) scanned in 1.04 seconds
  192.168.178.16/28

  1111 1111
     ^
    => 1111 = 15
      0-15
   * 16-31
     32-47
    ...

root@earthX200:~# nmap -sP -n 192.168.178.16/28
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-05 14:30 CEST
Nmap scan report for 192.168.178.24
Host is up (0.052s latency).
MAC Address: 84:0D:8E:50:AC:73 (Espressif)
Nmap scan report for 192.168.178.25
Host is up (0.059s latency).
MAC Address: 84:0D:8E:5A:80:59 (Espressif)
Nmap scan report for 192.168.178.29
Host is up (0.024s latency).
MAC Address: F0:81:73:56:20:63 (Amazon Technologies)
Nmap done: 16 IP addresses (3 hosts up) scanned in 0.59 seconds
  192.168.178.16/29

  1111 1111
       ^
     => 111 = 7
      0-7
      8-15
   * 16-23
    ...
root@earthX200:~# nmap -sP -n 192.168.178.16/29
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-05 14:31 CEST
Nmap done: 8 IP addresses (0 hosts up) scanned in 0.48 seconds
  192.168.178.27/29

  1111 1111
       ^
     => 111 = 7
      0-7
      8-15
     16-23
   * 24-31   <= 24<27
    ...
root@earthX200:~# nmap -sP -n 192.168.178.27/29
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-05 14:48 CEST
Nmap scan report for 192.168.178.24
Host is up (0.096s latency).
MAC Address: 84:0D:8E:50:AC:73 (Espressif)
Nmap scan report for 192.168.178.25
Host is up (0.088s latency).
MAC Address: 84:0D:8E:5A:80:59 (Espressif)
Nmap scan report for 192.168.178.29
Host is up (0.038s latency).
MAC Address: F0:81:73:56:20:63 (Amazon Technologies)
Nmap done: 8 IP addresses (3 hosts up) scanned in 0.80 seconds

Verschlüsselten USB Stick beim booten mounten

Vorwort

Ich habe das ganze auf meinem Orange Pi Zero mit Armbian 20.11.3 Focal getestet.

Notwendige Pakete installieren

Wenn es noch nicht geschehen ist muss folgendes Paket installiert werden.

root@orangepizero:~# apt install cryptsetup

Finden des USB Sticks

Zuerst müssen wir den USB-Stick finden

root@orangepizero:~# lsblk -p
NAME             MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
/dev/sda           8:0    1 115.7G  0 disk
└─/dev/sda1        8:1    1 115.7G  0 part
/dev/mmcblk0     179:0    0   3.7G  0 disk
└─/dev/mmcblk0p1 179:1    0   3.5G  0 part /
/dev/zram0       254:0    0    50M  0 disk /var/log
/dev/zram1       254:1    0 246.1M  0 disk [SWAP]

root@orangepizero:~# blkid
/dev/mmcblk0p1: UUID="b94b4648-cbb0-42ba-95e5-ba7c5d978a3b" TYPE="ext4" PARTUUID="1cac4ae8-01"
/dev/sda1: UUID="3de72a1a-cb9a-41c9-baff-d3d872248163" TYPE="crypto_LUKS" PARTUUID="9f599bf5-7d3c-4276-91f4-42b1954bf47b"
/dev/zram0: LABEL="log2ram" UUID="3e01a261-aea6-4f8e-a0f8-5ea5ba48eadd" TYPE="ext4"
/dev/zram1: UUID="b32030e6-f424-4225-b192-4eb6681a4595" TYPE="swap"

Unser Stick ist für dieses Beispiel auf /dev/sda1 zu finden. Mich interessiert die UUID. Einbinden über sdx sind fehlerhaft, wenn mehr als ein USB Stick eingesteckt wird.

Öffenen des verschlüsselten Laufwerks

Kann etwas dauern, gerade beim rechenschwachen OrangePi.

root@orangepizero:~# cryptsetup luksOpen /dev/disk/by-uuid/3de72a1a-cb9a-41c9-baff-d3d872248163 OBERON

Dann mounten wir das Laufwerk schon mal auf seinen zukünftigen Mount-Point

## Create Mount-Point
root@orangepizero:~# mkdir                    /media/OBERON

## Mount drive
root@orangepizero:~# mount /dev/mapper/OBERON /media/OBERON/

## Access for all users.
root@orangepizero:~# chown root:root -R       /media/OBERON
root@orangepizero:~# chmod 777                /media/OBERON/

Erstellen eines zusätzlichen Schlüssels für den USB-Stick

Da der USB Stick automatisch/headless eingebunden werden soll, müssen wir zunächst ein KeyFile erstellen.

## Verzeichnis erstellen, wo das KeyFile gespeichert wird.
root@orangepizero:~# mkdir ~/.keyfiles
## Ein randominisiertes KeyFile erstellen.
root@orangepizero:~# dd if=/dev/urandom of=/root/.keyfiles/OBERON_luks bs=1024 count=4
## Den randominisiertes KeyFile dem Volume als zusetzlichen Key zufügen.
cryptsetup luksAddKey /dev/disk/by-uuid/3de72a1a-cb9a-41c9-baff-d3d872248163 /root/.keyfiles/OBERON_luks

Eine Entschlüsselung des Laufwerkes ist mit dem bekannten Passwort weiterhin möglich. Aber nun auch mit dem KeyFile.

Vorbereiten für Reboot

Nun müssen abschließend noch zwei Dateien editiert werden.

  • vi /etc/fstab - damit der Stick gemountet wird.

...
## Add this entry
/dev/mapper/OBERON  /media/OBERON   ext4    defaults,rw 0   0
  • vi /etc/crypttab - damit der Stick entschlüsselt wird.

...
## Add this entry
OBERON  /dev/disk/by-uuid/3de72a1a-cb9a-41c9-baff-d3d872248163  /root/.keyfiles/OBERON_luks luks

Nach dem Reboot ist der USB nun dirket gemountet und kann von allen Usern benutzt werden.

Verschlüsselung von Dateien mittels GNU Privacy Guard

to test: docker-gpg

GNU Privacy Guard, abgekürzt GnuPG oder GPG, ist ein freies Kryptographiesystem. Es dient zum Ver- und Entschlüsseln von Daten sowie zum Erzeugen und Prüfen elektronischer Signaturen.

In diesem Beispiel zeige ich, wie GPG eingerichtet wird, Schlüssel ausgetauscht und Dateien ver-/entschlüsselt werden.

Einrichten von GPG zur persönlichen Verwendung

Zunächst einmal muss das eigene Schlüsselbund erzeugen werden und anschließend der öffentliche Teil exportiert und bereit gestellt werden.

[1. ]helmi@progisart ~]$ cat >"helmi.keyData" <<EOF
>     %echo Generating a basic OpenPGP key
>     Key-Type: DSA
>     Key-Length: 1024
>     Subkey-Type: ELG-E
>     Subkey-Length: 1024
>     Name-Real: Helmi Helm
>     Name-Comment: with stupid passphrase <helmi123>
>     Name-Email: helmi.helm@dockerworld.de
>     Expire-Date: 0
>     Passphrase: helmi123
>     # Do a commit here, so that we can later print "done" :-)
>     %commit
>     %echo done
> EOF
[2. ]helmi@progisart ~]$ gpg --batch --gen-key "helmi.keyData"
[3. ]helmi@progisart ~]$ gpg --output "/tmp/helmi_pub.gpg" --armor --export $(gpg --list-keys | tr -s ' ' | grep -E '^pub' | sed -E 's/.*\/(.*) .*/\1/g')
[4. ]helmi@progisart ~]$ scp "helmo"@gpg__"helmo":"/tmp/helmo_pub.gpg" /tmp
[5. ]helmi@progisart ~]$ gpg --import "/tmp/helmo_pub.gpg"
  • zu 1. ] Ein Schlüsselbund kann interaktiv oder im Batch erstellt werden. Für den Batch-Lauf muss der Inhalt des Schlüssel vorab in eine Datei gespeichert werden.

  • zu 2. ] Dann wird das Schlüsselbund erstellt.

  • zu 3. ] Danach kann der Public Key des Users exportiert werden.

  • zu 4. ] Dann wird der Public Key des Empfängers herunter geladen.

  • zu 5. ] Dessen Public Key wird dann in den eigenen Schlüsselbund importiert.

Verschlüsseln einer Datei

[1. ]helmi@progisart ~]$ cat >"/tmp/messageFrom_helmi" <<EOF
A message from Helmi Helm
EOF
[2. ]helmi@progisart ~]$ gpg --encrypt --armor --recipient "helmo.helm@dockerworld.de" --trust-model always "/tmp/messageFrom_helmi"
  • zu 1. ] Nachdem die auszutauschende Nachricht erstellt wurde …

  • zu 2. ] … wird diese mit dem öffentlichen Schlüssel des Empfängers verschlüsselt.

Entschlüsseln der Datei

[1. ]helmi@progisart ~]$ scp "helmo"@gpg__"helmo":"/tmp/messageFrom_helmo.asc" /tmp
[2. ]helmi@progisart ~]$ gpg --batch --yes --passphrase "helmi123" "/tmp/messageFrom_helmo.asc"
[3. ]helmi@progisart ~]$ cat "/tmp/messageFrom_helmo"
  • zu 1. ] Nachdem die verschlüsselte Nachricht geholt wurde …

  • zu 2. ] … kann der Empfänger diese mit seinem öffentlichen Schlüssel verschlüsselte Nachricht entschlüsseln. Hierzu benötigt er das Passwort für sein Schlüsselbund.

  • zu 3. ] Die entschlüsselte Nachricht liegt nun wieder im Klartext vor und der Inhalt kann angezeigt werden.

JSON als Table unter Oracle

Konnte es nicht so einfach finden, daher schreibe ich es hier einmal für euch auf.

Wie verarbeitet man ein JSON und gibt dies als Tabelle aus?

Hier die Lösung:

  with  DATA(js)
    as  (  select
  '
  { "stati":
    {
      "status":
      { "name":        "ungeprüft",
        "nummer":      1,
        "verfuegbar":  1
      },
      "status":
      { "name":        "geprüft",
        "nummer":      2,
        "verfuegbar":  1
      },
      "status":
      { "name":        "in Prüfung",
        "nummer":      3,
        "verfuegbar":  1
      },
      "status":
      { "name":        "im Einsatz",
        "nummer":      4,
        "verfuegbar":  0
      },
      "status":
      { "name":        "nicht verfügbar",
        "nummer":      5,
        "verfuegbar":  0
      },
      "status":
      { "name":        "Fehlteile",
        "nummer":      6,
        "verfuegbar":  1
      },
      "status":
      { "name":        "Lager",
        "nummer":      7,
        "verfuegbar":  1
      },
      "status":
      { "name":        "verliehen",
        "nummer":      8,
        "verfuegbar":  0
      }
    }
  }
  '
             from  dual
        )
     ,  VERFUEGBARKEIT
    as  (  select  j.*
             from  DATA d
                ,  json_table(  js
                             ,  '$.stati.status'
                                columns (
                                     NAME       VARCHAR(50) path '$.name'
                                  ,  NUMMER          NUMBER path '$.nummer'
                                  ,  VERFUEGBAR      NUMBER path '$.verfuegbar'
                             )
                  ) j
        )
select  *
  from  VERFUEGBARKEIT;

Alias fuer schnellen Verzeichniswechsel

Wenn in einem Verzeichnis viele ähnliche lautende Unterverzeichnis existieren, z.B. Log-Files oder Verzeichnisse eines Projektes mit ähnlichen Name, dann kann selbst der Mechnanismus mittels <TAB> nervig werden.

$ ls -1
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.01/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.02/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.03/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.04/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.05/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.06/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.07/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.08/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.09/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.10/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.14/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.15/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.16/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.17/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.18/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.19/
irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.20/

Ach wenn man noch tiefer in die Verzeichnisse rein möchte, dann hilft der Mechnanismus nicht weiter.

$ find | grep -E 'moe.*1[1-3]'
./1/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
./1/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
./1/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
./2/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
./2/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
./2/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
./3/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
./3/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
./3/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
./4/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
./4/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
./4/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
./5/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
./5/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
./5/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13

Zum leichteren navigieren habe ich mir hierzu einen ALIAS formuliert, den ich euch unten zum Download zur Verfügung gestellt haben. Ich habe den ALIAS <cq> für change quick in Anlehnung an <cp> für change directory genannte.

$ cq moe.*1[1-3]
[1]    ./irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
[2]    ./irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
[3]    ./irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
Type number: 2

Wie ihr am Beispiel sehen könnt, beherrscht der ALIAS auch RegEx.

Standardmäßig sucht der ALIAS nur in dem Verzeichnis selbst. Als zweitern Parameter kann optional noch eine Ziffer mitgegeben werden. Mittels dieser wird bestimmt, wie tief im Baum gesucht wird. Die Funktion leitet sich von

find -maxdepth

ab, entspricht also genau dem Verhalten.

$ cq moe.*1[1-3] 2
[1]    ./1/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
[2]    ./1/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
[3]    ./1/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
[4]    ./2/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
[5]    ./2/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
[6]    ./2/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
[7]    ./3/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
[8]    ./3/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
[9]    ./3/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
[10]    ./4/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
[11]    ./4/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
[12]    ./4/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
[13]    ./5/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.11
[14]    ./5/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.12
[15]    ./5/irgend.etwas.super.langes.wo.man.nicht.hin.navigieren.moechte.13
Type number: 9

Hier noch der Quelltext des ALIAS, optional könnte ihr ihn auch hier runter laden.

alias  cq='function _cq(){
  local toDir
  local dirNumber
  local searchPattern="${1}"
  local searchDepth="${2}"

  if [ -z "$searchDepth" ]; then
    searchDepth="1"
  fi

  if [[ "${searchPattern}" == */ ]]; then
    searchPattern=${searchPattern::-1}
  fi

  read -d " " -r -a toDir <<< $(find -maxdepth "${searchDepth}" -type d | grep -iE "${searchPattern}" | grep -vi clone)

    if [ ${#toDir[@]} == 0 ]; then
    echo "... found nothing for pattern ${searchPattern}"
  elif [ ${#toDir[@]} == 1 ]; then
    cd "${toDir[0]}"
  else
    for i in $(seq ${#toDir[@]}); do
      echo "[$i]    ${toDir[$i-1]}"
    done

    read -p "Type number: " dirNumber
    cd "${toDir[$dirNumber-1]}"
  fi

};_cq'

GIT Kommandos

Hier ein paar wichtige GIT Befehle und ihre Bedeutung.

Basic commands

## -----------------------------------------------------------------------------
## Clone ...
## ... a repository
git clone http://[username@]<base.url>/<repo.git>
## -----------------------------------------------------------------------------
## Commit ...
## ... with comment
git commit -m "Initial Commit"
## ... with timestamp as comment
git commit -m  $(date --iso-8601=seconds)
## -----------------------------------------------------------------------------
## Pull on all branches
git pull --all
## Push ...
## ... on all branches
git push --all -f
## ... special branch
git push -u origin DRAFT
## -----------------------------------------------------------------------------
## Branches ...
## ... create local Branch (and checkout)
git checkout -b DRAFT
## ... and publish to remote
git push -u origin DRAFT
## ... delete local Branch
git branch -d DRAFT
## ... and delete at remote
git push origin --delete DRAFT
## -----------------------------------------------------------------------------
## Add ...
## ... all
git add --all
## -----------------------------------------------------------------------------
## Diff ...
## ... of two explicit versions
git diff 335f02d165218a4f24f98d605200064065c6f25e..677457e992369954021fb9069e027845a6f3bd86
## ... from master 3 version in the past.
git diff master~3
## ... difference between last but one commit and last commit
git diff HEAD~
git diff @
## ... difference between second and third commit
git diff HEAD~2 HEAD~1

Configuration

## Edit the current configuration in VIM
git config --global -e

## Edit single configuration item
git config --global user.name "ProgIsArt"
git config --global user.email "progisart@gmx.de"
git config --global core.editor "gvim --nofork '%*'"
git config --global core.editor "vim"
git config --global credential.helper store

## Show the current configuration
git config --global --list

## Get remote url as single line
git config --get remote.origin.url

## Proxy-Settings and HTTP setting
##   Unspecific settings ...
##   ... proxy settings
git config --global http.proxy http://<username>:<passwd>@<url>:<port>
##   ... ignore errors with selfsigned/unsecure certificates
git config --global http.sslVerify false

##   (but GIT do not know a no_proxy settting, therefore to setup specific settings)
##   Specific settings ...
##   ... proxy settings
git config --global http.<repo-url:http[s]//:...>.proxy http://<username>:<passwd>@<url>:<port>
##   ... ignore errors with selfsigned/unsecure certificates
git config --global http.<repo-url:http[s]//:...>.sslVerify false



## Fix the EOL setting to unix format
git config --global core.autocrlf false
git config --global core.eol lf

Special commands

## -----------------------------------------------------------------------------
## Checkout version by date
git checkout $(git rev-list -n 1 --first-parent --before="2020-02-02 00:00:00" master)


## -----------------------------------------------------------------------------
## Create new repository from the command line
touch README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://<base.url>/<repo.git>
git push -u origin master

## Push existing repository from the command line
git remote add origin https://<base.url>/<repo.git>
git push -u origin master
## ... alternative ...
git push -u origin --all
git push origin --tags


## -----------------------------------------------------------------------------
## Importent on WINDOWS, open help on command line and not in the browser.
git <command> -h


## -----------------------------------------------------------------------------
## Create a tag with comment and push to remote
git tag -a MlStn_0.3.0 -m 'Milestone 0.3.0'
git push origin --tags
git tag -l -n5

## Delete a tag from local and remote
git tag -d v2.2.0.0
git push --delete origin v2.2.0.0
git tag -l -n5

## How have create a tag
git for-each-ref --format '%(refname) %09 %(taggerdate) %(subject) %(taggeremail)' refs/tags  --sort=taggerdate

## -----------------------------------------------------------------------------
## Moving files and directories to a new repository
git remote rm origin
git remote add origin  https://<base.url>/<repo.git>
git push --set-upstream origin master


## -----------------------------------------------------------------------------
## Create and apply a patch
git diff HEAD >a.patch
patch -p1 <../a/a.patch

Rebase

## -----------------------------------------------------------------------------
## Rebase local
git rebase -i HEAD~2

## -----------------------------------------------------------------------------
## Rebase remote
git rebase -i origin/DRAFT~2 DRAFT
git push origin +DRAFT

Settings on OS level (…​ hier bevorzugt Linux Syntax)

## -----------------------------------------------------------------------------
## Checkout version by date
## ... with git-bash on Windoof add to [GIT-HOME]/etc/profile.d/bash_profile.sh
export  http_proxy=http://<username>:<passwd>@<url>:<port>
export https_proxy=http://<username>:<passwd>@<url>:<port>
export    no_proxy=example.com,192.0.2.42