Verzeichnisse mit ENCFS verschlüsseln
EncFS ist einfach Methode ein Verzeichnis zu verschlüsseln. Aber es ist keine sicher.
Hier der Warnhinweis, den man bei der Installation angezeigt bekommmt. (Übersetzt ins Deutsche)
Gemäß einer Sicherheitsüberprüfung von Taylor Hornby (Defuse Security) ist die aktuelle Implementierung von Encfs anfällig oder potenziell anfällig für verschiedene Arten von Angriffen. Ein Angreifer mit Lese-/Schreibzugriff auf verschlüsselte Daten könnte beispielsweise die Entschlüsselungskomplexität für nachfolgend verschlüsselte Daten herabsetzen, ohne dass dies von einem legitimen Benutzer bemerkt wird, oder könnte durch Zeitanalysen Informationen ableiten.
Vorbereitung
Installation von encfs
[root@progisart:/tmp]# apt-get install encfs
Es müssen zwei Verzeichnisse erstellt werden, das Ziel und das Quellverzeichnis:
[user@progisart:/tmp]$ mkdir -v .crypt crypt mkdir: created directory '.crypt' mkdir: created directory 'crypt'
Anschließend können die zwei zuvor erstellten Verzeichnisse mithilfe des Verschlüsselungssystems EncFS miteinander verknüpft werden. Bei der ersten Verwendung dieser Funktion müssen verschiedene Konfigurationsfragen beantwortet werden, insbesondere zur Auswahl des gewünschten Verschlüsselungsalgorithmus und dessen spezifischen Einstellungen.
EncFS, als Verschlüsselungssystem für das Dateisystem, funktioniert ausschließlich mit absoluten Pfaden in der Verzeichnisstruktur. Diese technische Einschränkung bedeutet, dass bei der Verwendung des Befehls immer der vollständige Pfad, beginnend vom Wurzelverzeichnis, angegeben werden muss.
[user@progisart:/tmp]$ encfs "${PWD}/.crypt" "${PWD}/crypt" Creating new encrypted volume. Please choose from one of the following options: enter "x" for expert configuration mode, enter "p" for pre-configured paranoia mode, anything else, or an empty line will select standard mode. ?> p Paranoia configuration selected. .... .... .... .... New Encfs Password: Verify Encfs Password: [user@progisart:/tmp]$
Nutzung
Die beiden Verzeichnisse sind nun durch eine logische Verknüpfung miteinander verbunden. Wenn eine Datei im Zielverzeichnis erstellt, geschrieben oder angezeigt wird, ist sie physikalisch im verschlüsselten Zielverzeichnis gespeichert.
[user@progisart:/tmp]$ find .crypt crypt .crypt .crypt/.encfs6.xml crypt [user@progisart:/tmp]$ cd crypt/ [user@progisart:/tmp/crypt]$ touch huhu.txt haha.txt hihi.txt [user@progisart:/tmp/crypt]$ cd .. [user@progisart:/tmp]$ find .crypt crypt .crypt .crypt/6v5s02ao2-hYpi,v8dqlIjwj .crypt/BIfXW9HfxlaubuJDCephESFB .crypt/.encfs6.xml .crypt/Nt3GdcJ3DtdxVEODj4mNoyqF crypt crypt/haha.txt crypt/huhu.txt crypt/hihi.txt [user@progisart:/tmp]$
Die Verknüpfung des verschlüsselten Verzeichnisses lässt sich zuverlässig mittels des Befehls fusermount
trennen und aufheben, während der auf den ersten Blick intuitivere und naheliegende Befehl encfs -u
in der aktuellen Version leider nicht wie erwartet funktioniert.
[user@progisart:/tmp]$ fusermount -u "${PWD}/crypt" [user@progisart:/tmp]$ find .crypt crypt .crypt .crypt/6v5s02ao2-hYpi,v8dqlIjwj .crypt/BIfXW9HfxlaubuJDCephESFB .crypt/.encfs6.xml .crypt/Nt3GdcJ3DtdxVEODj4mNoyqF crypt [user@progisart:/tmp]$
Eigenen Schlüssel nach AWS Key Management hochladen
In diesem Abschnitt wird beschrieben, wie wir einen Custom managed Key in AWS aus lokalem Schlüsselmaterial erstellen.
Erstellen des lokalen Schlüssel
Einen lokalen Schlüssel mittels OpenSSL erstellen.
[user@progisart:~/dev/kms]$ openssl rand -out myPlainKeyMaterial.bin 32 [user@progisart:~/dev/kms]$ ls -al myPlainKeyMaterial.bin -rw-r--r-- 1 user user 32 Jan 24 11:17 myPlainKeyMaterial.bin
Erstellen eine Schlüssels in AWS mittels AWS-CLI
@see: aws kms
Erstellen eine neuen, leeren Schlüssel in AWS
[user@progisart:~/dev/kms]$ aws kms create-key --origin EXTERNAL .... .... .... ....
Download des Key material
Öffne die AWS Management Console und navigiere zu
-
Security, Identity, & Compliance> Key Management Service> Customer-managed keys> Key ID: yourKeyId:: Key material
-
Import key material
: Download wrapping public key and import token
-
Kopiere dir das Material in dein Arbeits-Verzeichnis und entpacke es.
[user@progisart:~/dev/kms]$ cp ~/Downloads/Import_Parameters_357fea84-6620-4656-ab0c-5b27b19ecd79_01241235.zip . [user@progisart:~/dev/kms]$ unzip Import_Parameters_357fea84-6620-4656-ab0c-5b27b19ecd79_01241235.zip Archive: Import_Parameters_357fea84-6620-4656-ab0c-5b27b19ecd79_01241235.zip extracting: WrappingPublicKey.bin extracting: ImportToken.bin extracting: README.txt [user@progisart:~/dev/kms]$ ls ImportToken.bin Import_Parameters_357fea84-6620-4656-ab0c-5b27b19ecd79_01241235.zip README.txt WrappingPublicKey.bin myPlainKeyMaterial.bin [user@progisart:~/dev/kms]$
[user@progisart:~/dev/kms]$ openssl pkeyutl -in myPlainKeyMaterial.bin -out encMyPlainKeyMaterial.bin -inkey WrappingPublicKey.bin -keyform DER -pubin -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
Upload des eigenen Schlüssels Materials
Zurück in der AWS Management Console solltest du noch immer in dem Dialog sein, wo du das Import key material
heruntergeladen hast. Gehe auf Next
-
Upload your wrapped key material> Encrypted key material and import token
-
Wrapped key material> Choose file
: encMyPlainKeyMaterial.bin -
Import token> Choose file
: ImportToken.bin
-
Für den Import ist jetzt alles fertig. Um den Schlüssel jedoch besser identifizieren zu können, ist es sinnvoll, einen Alias zu vergeben.
[user@progisart:~/dev/kms]$ aws kms create-alias --alias-name myKey --target-key-id 357fea84-6620-4656-ab0c-5b27b19ecd79
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\{nbsp}{nbsp}{nbsp}{nbsp}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
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 "{nbsp}{nbsp}{nbsp}{nbsp}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
Alias für rekursive GIT Kommandos
Der Trend zu Microservices oder kleineren Funktionseinheiten ist ja erst einmal zu befürworten.
Konsequenz daraus ist jedoch, dass jeder Service sein eigenes GIT Repo bekommt. Und das wiederum führt unweigerlich zur allmorgendlichen Update Hölle. Ich möchte jetzt auch kein Statement dazu abgeben, ob die Projekte gut und richtig aufgesetzt sind.
Letztendlich bin ich der DevOps und nicht der Entwickler. Ich muss damit arbeiten, was man mir liefert. Ich weiß nur, dass ich jeden Morgen so um die 60 Projekt aktualisieren muss. Selbst ich als Konsolen-Anhänger komme da die Grenzen meiner Effizienz. Zwar kann man SHELL-Scripte für solche Aufgaben erstellen. Die müssen dann aber auch immer angepasst und gepflegt werden.
Also, weil das nicht sinnvoll ist, habe ich für diese Aufgabe einen ALIAS <gall> (für git all) geschrieben.
progisart@earthX200:~/github$ gall 'git pull'
>>>>>>>>>> /home/progisart/github/rpi-ai
Bereits aktuell.
>>>>>>>>>> /home/progisart/github/creative-theme-jekyll-new
Bereits aktuell.
>>>>>>>>>> /home/progisart/github/Configs
Bereits aktuell.
>>>>>>>>>> /home/progisart/github/wiki-jekyll
Bereits aktuell.
>>>>>>>>>> /home/progisart/github/wiki-jekyll/jekyll/data
Bereits aktuell.
progisart@earthX200:~/github$
progisart@earthX200:~/github$ gall 'git pull' data
>>>>>>>>>> /home/progisart/github/wiki-jekyll/jekyll/data
Bereits aktuell.
<gall> sucht vom Start Verzeichnis aus rekursiv alle Verzeichnisse zusammen, in denen ein GIT-Repo ausgecheckt worden ist und führt dann auf diesen Verzeichnissen das übergebene Kommando aus.
Das kann ein git pull sein. Aber auch ein git add -A oder ein git commit -m `….'. Also, man kann alles damit machen, auch Schabernack. Letztendlich kommt auf die eigenen Risiko-Bereitschaft an.
Hier noch der Quelltext des ALIAS, optional könnte ihr ihn auch hier runter laden.
alias gall='function _gall(){
if [ "${2}" == "" ]; then
find -type d | grep -E "\.git$" | sed "s|\/\.git||" | sed "s|^\.|$PWD|" | xargs -I{} bash -c "cd {} ; echo '\''>>>>>>>>>> {}'\'' ; ${1}"
else
find -type d | grep -E "\.git$" | grep -Ei "${2}" | sed "s|\/\.git||" | sed "s|^\.|$PWD|" | xargs -I{} bash -c "cd {} ; echo '\''>>>>>>>>>> {}'\'' ; ${1}"
fi
};_gall'
Abfragen über die AWS CLI und JQ
AWS CLI ist eine leisungfähige Möglichkeit, seine Infrastruktur über die Konsole zu erforschen. Die Auswertung ist allerdings auch schon mal erschlagend.
Sofern die Ausgabe als JSON erfolgt, eigentlich der Standard für die AWS CLI, dann kann man die Ausgabe erfolgreich mit JQ kombinieren, um das Wesentliche sichtbar zu machen.
Hier ein paar Bespiele
aws --region=eu-central-1 iam list-policies | jq '.Policies[] | select( .Arn | contains("763904092123")) | { policyName: .PolicyName, arn: .Arn}' aws --region=eu-central-1 iam list-roles | jq '.Roles[] | select( .Arn | contains("763904092123")) | {roleName: .RoleName, arn: .Arn}' aws --region=eu-central-1 logs describe-log-groups | jq '.logGroups[] | select( .arn | contains("763904092123")) | { logGroupName: .logGroupName, arn: .arn}' aws --region=eu-central-1 iam list-instance-profiles | jq '.InstanceProfiles[] | select( .Arn | contains("763904092123")) | { instanceProfileName: .InstanceProfileName, arn: .Arn}' aws --region=eu-central-1 ec2 describe-security-groups | jq '.SecurityGroups[] | select( .GroupName | contains("spot")) | { groupName: .GroupName, ipPermissionsFromPort: .IpPermissions[].FromPort}' aws --region=eu-central-1 s3 ls | tr -s ' ' | cut -d ' ' -f 3 | xargs -rI{} aws s3api get-bucket-acl --bucket {}
HTH
ProgIsArt
AWS CLI mit MFA
Einleitung
Die AWS CLI ohne MFA ist innerhalb einer Sicherheitsarchitektur so ziemlich das Unsicherste, was man sich vorstellen kann. Hat man einmal seine Credentials erstellt, laufen sie nicht ab und dass selbst dann, wenn man einen Administrator Account hat.
Daher ist die Einrichtung einer MFA gerade hier besonders wichtig.
Im Folgenden wird beschrieben, wie die MFA zusammen mit der AWS CLI zu verwenden ist.
TL;DR
-
Installiere die AWS CLI
-
Richte deine Umgebung mittels
aws configure
ein. -
Ergänze
.aws/config
um deine mfa_serial:ubuntu@local:~$ cat .aws/config [default] region = eu-central-1 output = yaml mfa_serial = arn:aws:iam::123456789012:mfa/prog_is_art
-
Erstelle eine Datei
/usr/local/bin/awscliMFA
#!/bin/bash set -u expiration='' while read -r line; do cmd='' key=$(echo $line | cut -d ':' -f 1 ) value=$(echo $line | cut -d ':' -f 2-99 | sed -E 's|^[ ]*||g' ) if [ "${key}" == 'Expiration' ];then expiration="${value}" elif [ "${key}" == 'AccessKeyId' ];then cmd='export AWS_ACCESS_KEY_ID='"${value}"'' elif [ "${key}" == 'SecretAccessKey' ];then cmd='export AWS_SECRET_ACCESS_KEY='"${value}"'' elif [ "${key}" == 'SessionToken' ];then cmd='export AWS_SESSION_TOKEN='"${value}"'' fi eval "${cmd}" done < <(aws sts get-session-token --output yaml --serial-number $(aws configure get mfa_serial) --token-code "${1}" | tr -s ' ' | grep -E 'AccessKeyId|SecretAccessKey|SessionToken|Expiration') echo "your session will expire at ${expiration}" echo 'to unset changes and return to normal state, type:' echo ' unset $(env | grep -E '"'"'^AWS'"'"' | grep -v '"'"'PROFILE'"'"' | cut -d '"'"'='"'"' -f 1)'
-
Starte den Befehl
. awscliMFA 1****1
-
Wenn die 12h in für die Session abgelaufen sind oder wenn das Profil wechseln muss resete deine Umgebung
unset $(env | grep -E '^AWS' | grep -v 'PROFILE' | cut -d '=' -f 1)
Voraussetzungen
Bevor mit dem eigentlichen Thema angefangen werden kann, müssen zunächst einmal ein paar Vorbedingungen erfüllt sein.
BASH-Shell
Es wird davon ausgegangen, dass auf einem Linux-System mit BASH-Shell gearbeitet wird.
Unter Linux oder Mac gibt es die naturgemäß. Auf einem Windows kommt man aber auch ganz einfach dran. Hier eine kleine Liste der Möglichkeiten:
WSL (Windows Subsystem for Linux)
- Mit Sicherheit eine sehr gute Lösung.
- Vorteil: sehr einfach zu installieren. - Nachteil: es gibt nur Eine.
Multipass
- Auch eine gute Lösung
- Vorteil: - Immer noch recht einfach zu installieren. - Man kann beliebig viele aufmachen. - Man kann in der Umgebung eine Docker-Damoen starten, das geht in der WSL nicht. - Nachteil: - Sie läuft nicht so stabil und fehlerfrei wie die WSL. Es ist aber auch nicht so, dass sie am laufenden Band abstürzt.
Docker-Container
- Die flexibelste, aber auch die Lösung, für die man die meisten Vorkenntnisse benötigt.
- Vor- und Nachteile schenk ich mir hier. Die werden die, die diese Lösung ins Auge fassen hoffentlich kennen.
AWS CLI Installation
Wer die AWS CLI noch nicht installiert hat, der findet hier eine gute Anleitung:
Wichtig hier auch der Teil, wie eine erste Configuration erstellt wird. Die wird nämlich benötigt.
Nutzung der AWS CLI mit MFA
Nun zum eigentlichen Hauptthema.
Wer mehr über das Thema wissen will, der kann das Original hier nachlesen:
Wer nur an der Kernaussage interessiert ist, der sollte einfach hier weiter machen.
Die Basics
Das Wesentliche in Kürze:
aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token
arn-of-the-mfa-device
- die ARN eures virtuellen MFA-Device, z.B. der Google-Authenticator oder was auch immer ihr für eine Tool verwendet.
- z.B. *arn:aws:iam::123456789012:mfa/prog_is_art*
code-from-token
- der gerade aktuelle Token.
Im Einsatz
ubuntu@local:~$ aws sts get-session-token --output yaml --serial-number arn:aws:iam::123456789012:mfa/maxmustermann --token-code 1****1 Credentials: AccessKeyId: A******************N Expiration: '2022-05-01T22:38:09+00:00' SecretAccessKey: 9**************************************5 SessionToken: I*************************************************************************************************************************************************************************************************************************************************************************** ******************************************************************************************************************************************************************************************************************************************************************************************** ***********************************************************************************************************************g ubuntu@local:~$
Hinterlegen der MFA Serial Number
Die MFA Serial Number kann man sich am Profil (aws configure, siehe oben) hinterlegen:
ubuntu@local:~$ cat .aws/config [default] region = eu-central-1 output = yaml mfa_serial = arn:aws:iam::123456789012:mfa/prog_is_art
Sie kann dann ausgelesen werden:
ubuntu@local:~$ aws sts get-session-token --output yaml --serial-number $(aws configure get mfa_serial) --token-code 1****1 Credentials: AccessKeyId: A******************N Expiration: '2022-05-01T22:38:09+00:00' SecretAccessKey: 9**************************************5 SessionToken: I*************************************************************************************************************************************************************************************************************************************************************************** ******************************************************************************************************************************************************************************************************************************************************************************************** ***********************************************************************************************************************g ubuntu@local:~$
Session-Credentials automatisch übernehmen
Damit ich nicht jedes Mal den Output extrahieren und kompliziert in meine Umgebung-Variablen extrahieren muss, habe ich folgendes Script geschrieben:
#!/bin/bash set -u expiration='' while read -r line; do cmd='' key=$(echo $line | cut -d ':' -f 1 ) value=$(echo $line | cut -d ':' -f 2-99 | sed -E 's|^[ ]*||g' ) if [ "${key}" == 'Expiration' ];then expiration="${value}" elif [ "${key}" == 'AccessKeyId' ];then cmd='export AWS_ACCESS_KEY_ID='"${value}"'' elif [ "${key}" == 'SecretAccessKey' ];then cmd='export AWS_SECRET_ACCESS_KEY='"${value}"'' elif [ "${key}" == 'SessionToken' ];then cmd='export AWS_SESSION_TOKEN='"${value}"'' fi eval "${cmd}" done < <(aws sts get-session-token --output yaml --serial-number $(aws configure get mfa_serial) --token-code "${1}" | tr -s ' ' | grep -E 'AccessKeyId|SecretAccessKey|SessionToken|Expiration') echo "your session will expire at ${expiration}" echo 'to unset changes and return to normal state, type:' echo ' unset $(env | grep -E '"'"'^AWS'"'"' | grep -v '"'"'PROFILE'"'"' | cut -d '"'"'='"'"' -f 1)'
Ausführung:
ubuntu@local:~$ which awscliMFA /usr/local/bin/awscliMFA ubuntu@local:~$ . awscliMFA 1****1 your session will expire at '2022-05-01T22:58:37+00:00' to unset changes and return to normal state, type: unset $(env | grep -E '^AWS' | grep -v 'PROFILE' | cut -d '=' -f 1) ubuntu@local:~$ env | grep -E '^AWS' | grep -v 'PROFILE' AWS_SECRET_ACCESS_KEY=H**************************************k AWS_ACCESS_KEY_ID=A******************M AWS_SESSION_TOKEN=I************************************************************************************************************************************************************************************************************************************************************************* ******************************************************************************************************************************************************************************************************************************************************************************************** *************************************************************************************************************************c ubuntu@local:~$
Damit das hier nicht untergeht
- ubuntu@local:~$ . awscliMFA 1****1
- der Punkt vor dem eigentlichen Befehl ist wichtig (sourcen!!)
-
unset $(env | grep -E '^AWS' | grep -v 'PROFILE' | cut -d '=' -f 1)
-
bevor eine neue Session über MFA freigeschaltet werden kann, müssen die AWS-Umgebungsvariablen gelöscht werden. Sie überschreiben nämlich die Variablen der Konfiguration.
-
Ihr habt nun eine 12h Session unter der ihr arbeiten könnt. Sind die 12h vorbei, müsst ihr neue Credentials erstellen.
HTH
ProgIsArt
CD Tracks umbenennen
Ich kaufe mir tatsächlich noch CD’s. Hören tue ich sie natürlich nicht am CD-Player. Daher digitalisiere ich sie mir immer.
Ist ja mit Ubuntu auch ganz einfach. … CD einlegen, kopieren, fertig.
Track 1.wav Track 2.wav Track 3.wav Track 4.wav ...
Bleibt die Arbeit mit dem Umbenennen. Alles danach kann ganz einfach mit EasyTag erledigt werden.
Für das Umbenennen habe ich mir daher ein Shell-Script geschrieben.
ripAssist
main param | sub param | description |
---|---|---|
audio-book |
handle audiobook |
|
name |
All tracks will be renamed by this string. e.g. `Lord of the rings' will rename CD09/Track 5.wav to 0905.Lord of the rings.wav. |
|
cd |
handle single cd |
|
file |
path/name of the file contains real track names. |
|
create-repo |
preparation before extract |
|
amount |
amount 12 will create subdirs CD01 - CD 12 |
|
mock |
create mockdata for testing. Create in each CDXX folder empty files named Track 1.wav - Track 15.wav. |
|
–help |
print help |
HTH
ProgIsArt
Bilddaten in ASCII-Dokument einbetten
Es ist mir nun an verschieden Stellen untergekommen. Daher hier eine kurze Dokumentation, wie man Bilddaten Base64 encodiert und in eine Dokument einbettet.
Nehmen wir ein sehr kleines Bild:
Dieses Bild kann unter Linux sehr einfach in einen Base64 String encodiert werden:
cat www.w3.org.ico | base64
Raus kommt ein sehr langer String.
Diesen kann man dann in Markdown wie folgt als Bild verwenden:
![W3CLogo][W3CLogo] [W3CLogo]: data:image/png;base64,AAAB.....AA=
oder in HTML
<img src="data:image/png;base64,AAAB.....AA=" alt="www.w3.org.ico" border="0">
Bezüglich des Platzbedarfs auf der Platte muss man leider feststellen, dass der Platzbedarf etwas größer geworden ist.
[progisart@linux tmp]$ cat www.w3.org.ico | base64 >www.w3.org.txt [progisart@linux tmp]$ ls -al | grep w3 -rw-r--r--@ 1 progisart progisart 6518 14 Dez 13:24 www.w3.org.ico -rw-r--r-- 1 progisart progisart 8693 14 Dez 14:19 www.w3.org.txt
Durchsuchen eines MAVEN Repositories
Ich habe keine Ahnung, vielleicht ist das was ich hier mache total untypisch. Aber wenn ich mit Java und Maven programmiere komme ich immer wieder in die Verlegenheit wissen zu müssen, in welchem JAR denn nun eigentlich eine Klasse liegt, die mein Projekt gerade benötigt. Man weiß, dass das JAR auf der Platte liegt, aber man weiß nicht, in welchem.
Ich hatte hierzu schon eine Menge properitärer Lösung, dies ist nun die beste die ich mir erarbeitet habe.
#!/bin/bash case "${1}" in '--cache') if [ -f 'm2Idx.cache' ]; then cp m2Idx.cache m2Idx-$(date --iso-8601=minutes)-bak.cache; fi echo >m2Idx.cache while read -r line; do echo "${line}" echo "${line}" >>m2Idx.cache done < <(find -type f | grep -E '\.jar$' | xargs -rI{} bash -c 'echo "### {}" ; jar -tf "{}"') ;; '--search') pattern="${2}" currentJar="" relevantData=$(cat m2Idx.cache | grep -E "${pattern}|^### " | cat -n -) while read -r match; do matchNumber=$(echo "${match}" | sed -E 's|([0-9]*)(.*)|\1|g') matchName=$( echo "${match}" | sed -E 's|([0-9]*\s*)(.*)|\2|g') packageName='' while [ "${packageName}" == '' ]; do packageName=$(echo "${relevantData}" | sed -n -e ${matchNumber},${matchNumber}p | grep -E '^\s*[0-9]*\s*###\s*' | sed -E 's|^\s*[0-9]*\s*###\s*||') matchNumber=$((matchNumber-1)) done echo ">>> ${packageName}" echo "${matchName}" done < <(echo "${relevantData}" | grep -Ev '^\s*[0-9]*\s*###') ;; '--dep') searchPattern="${2}" echo ' <dependency>' while read -r line; do echo " ${line}" done < <(find -type f | grep -E '\.pom$' | grep "${searchPattern}" | xargs -rI{} cat '{}' | grep -E '<(groupId|artifactId|version)>' | sed -E 's/(\s)*//g') echo ' </dependency>' ;; *) echo "Option was something else: '${1}'";; esac
Wie funktioniert das Ganze: * mvnIdx –cache: muss als ersten aufgerufen werden und legt eine Cache-Datei an, damit die Suche schneller wird. * mvnIdx –search: sucht nach einer Übereinstimmung. Z.B.
progisart@:~/.m2/repository$ mvnIdx --search DERVisibleString >>> ./org/bouncycastle/bcprov-jdk15on/1.62/bcprov-jdk15on-1.62.jar org/bouncycastle/asn1/DERVisibleString.class >>> ./org/bouncycastle/bcprov-jdk15on/1.62/bcprov-jdk15on-1.62-javadoc.jar org/bouncycastle/asn1/DERVisibleString.html >>> ./org/bouncycastle/bcprov-jdk15on/1.62/bcprov-jdk15on-1.62-sources.jar org/bouncycastle/asn1/DERVisibleString.java
-
mvnIdx –dep: macht den best guess was die mögliche Dependency für die eigene POM angeht.
progisart@:~/.m2/repository$ mvnIdx --dep ./org/bouncycastle/bcprov-jdk15on/1.62/bcprov-jdk15on-1.62 <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.62</version> </dependency>
HTH
ProgIsArt
Text-to-Speech TTL unter Linux
Hier eine Beschreibung, wie man TTL für sich unter Ubuntu einrichtet.
ESpeak installieren und testen
## Install necessary packages
root@progIsArt:~# apt install espeak
## First stupid test.
helmi@progIsArt:~$ espeak 'huhu'
## An other test
helmi@progIsArt:~$ espeak 'Speech synthesis is the artificial production of human speech. A computer system used for this purpose is called a speech computer or speech synthesizer, and can be implemented in software or hardware products. A text-to-speech TTS system converts normal language text into speech; other systems render symbolic linguistic representations like phonetic transcriptions into speech.'
## Reduce speed
helmi@progIsArt:~$ espeak -s 145 'Speech synthesis is the artificial production of human speech. A computer system used for this purpose is called a speech computer or speech synthesizer, and can be implemented in software or hardware products. A text-to-speech TTS system converts normal language text into speech; other systems render symbolic linguistic representations like phonetic transcriptions into speech.'
## Output in german
helmi@progIsArt:~$ espeak -v de -s 145 'Unter Sprachsynthese versteht man die künstliche Erzeugung der menschlichen Sprechstimme. Ein Text-to-Speech-System TTS oder Vorleseautomat wandelt Fließtext in eine akustische Sprachausgabe.'
@see Bei Problemen mit der Sprachausgabe: SoundTroubleshootingGuide
Stimmen nachinstallieren
Die Basisstimme ist extrem synthetisch, daher sollte man lieber ein paar wohlklingendere Stimmen nachinstallieren.
## List of all installed voices
root@progIsArt:~$ espeak --voice
## List of all available german voices
root@progIsArt:~$ espeak --voice=de
## Before you can use other voices you have to install Mbrola
root@progIsArt:~$ apt install mbrola
## The voices are not includes, they have to be installed separately
# ... check for available voices
root@progIsArt:~$ apt search mbrola | grep -E '^mbrola\-(de|en)'
# ... install some of them
root@progIsArt:~$ apt install mbrola-en1 mbrola-de7
# ... test the new voice
helmi@progIsArt:~$ espeak -v mb-de7 -s 145 'Unter Sprachsynthese versteht man die künstliche Erzeugung der menschlichen Sprechstimme. Ein Text-to-Speech-System TTS oder Vorleseautomat wandelt Fließtext in eine akustische Sprachausgabe.'
Text aus der Zwischenablage vorlesen
Auf dem Weg zur Vollautomatisierung hier noch ein Test, wie man Text aus der Zwischenablage abspielt
## Installation necessary packages
root@progIsArt:~$ apt install xsel
## ... test
helmi@progIsArt:~$ espeak -v mb-de7 -s 145 "$(xsel)"
Script für die Ausgabe aus der Zwischenablage anlegen
Script erzeugen
Lege dies Script in ~/bin an.
-
talk2me Script
#!/bin/bash
case "${1}" in
'en') echo 'lang=mb-en1' >"${0}.conf" ;;
'de') echo 'lang=mb-de7' >"${0}.conf" ;;
'-9') killall espeak;;
*) espeak -v "$(cat "${0}.conf" | grep -vE '^#' | grep -E '^lang' | sed -E 's|(^lang\=)(.*)|\2|g')" -s 145 "$(xsel)"
;;
esac
helmi@progIsArt:~/bin$ chmod 755 talk2me
Test auf der Console
helmi@progIsArt:~/bin$ cd ~
helmi@progIsArt:~$ talk2me en
helmi@progIsArt:~$ talk2me
helmi@progIsArt:~$ talk2me de
helmi@progIsArt:~$ talk2me
Festlegen einer Tastenkombination für diesen Befehl
Gehe zu Einstellungen → Tastatur → Tasturkürzel.
Ganz nach unten auf das + Zeichen.
Name: Talk To Me Befehl: talk2me Tastenkombination: Super + Y
Zum Testen einen beliebigen Text markieren und dann Super + Y drücken. Die Textausgabe sollte generiert werden.
Tip
Wenn versehentlich ein sehr langer Text markiert wurde oder die Ausgabe doppelt gestartet wurde: * die Ausgabe kann durch den Befehl talk2me -9 beendet werden.
HTH
ProgIsArt
Zentrales Verzeichnis für alle mittels SMB bereitstellen
Wie schon im BLOG davor findet die Installation auf einem Orange Pi Zero mit Armbian 20.11.3 Focal statt.
Pakete installieren
Folgende Pakete müssen installiert werden.
root@progisart-funk:~# apt install samba cifs-utils smbclient
Anpassen der Konfiguration
Nach der Installation gibt es die Default-Konfiguration für den Samba Daemon. Von ihr erstelle ich ein Backup und erzeuge eine Konfigurations-Datei ohne Kommentare und Leerzeilen.
root@progisart-funk:~# cp /etc/samba/smb.conf /etc/samba/smb.conf_backup root@progisart-funk:~#
grep -v -E "^#|^;" /etc/samba/smb.conf_backup | grep . > /etc/samba/smb.conf
In diese Konfiguration füge ich nun folgendes ein. - vi /etc/samba/smb.conf
[public]
comment = public anonymous access
path = /var/samba/
writeable = yes
browseable = yes
public = yes
create mask = 0777
directory mask = 0777
force user = root
Diese Konfiguration macht, was auch schon in der Überschrift steht. Jeder kann sich hier ohne Authentifizierung anmelden, Verzeichnisse und Dateien anlegen aber auch löschen. Unnötig zu erwähnen, dass dies keine Produktions-Konfiguration ist.
Damit die Änderungen greifen, muss die Konfiguration neu eingelesen werden und der SMB Daemon neu gestartet werden.
root@progisart-funk:~# systemctl reload smbd
root@progisart-funk:~# systemctl restart smbd
Zugriff auf das SMB
Über den Gnome File Manager kann man nun ganz einfach auf die Freigabe zugreifen.