added new Bash scripts

This commit is contained in:
Steffen Vogel 2020-12-31 12:35:38 +01:00
parent 2b33de5b6a
commit e235b1824f
15 changed files with 683 additions and 0 deletions

View file

@ -0,0 +1,51 @@
#!/bin/bash
##
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
set -e
if [ $# -ne 2 ]; then
echo "Usage: $(basename $0) SOURCE REPO"
exit 1
fi
SRC=$1
REPO=$2
RESTIC="/usr/local/bin/restic"
# Install Restic
ssh ${SRC} <<ENDSSH
export RESTIC_REPOSITORY="s3:http://moon.int.0l.de:9001/${REPO}"
if [ "${REPO}" == "mail.0l.de" ]; then
export RESTIC_PASSWORD="Ca8vut7Y5hksuc1IkZfsrBf7ZKnHZwMYofLCWlmCPpJAMgqciwTZ5yxQUlUrii7h"
else
export RESTIC_PASSWORD="NtogK'D~>)r%2g'{-gm#rWak<EKu1W5mri)E8/dWD|5.\NP}wC*(Q#{>*M_SiJ\i"
fi
export AWS_ACCESS_KEY_ID="restic"
export AWS_SECRET_ACCESS_KEY="akuuphieyaizieGaneocheituGhe9oreagohzie6go4Euzai8ail2do7pohRai0e"
# Install or update restic
if ! [ -x ${RESTIC} ]; then
curl -qL https://github.com/restic/restic/releases/download/v0.9.5/restic_0.9.5_linux_amd64.bz2 | bunzip2 > ${RESTIC}
chmod +x ${RESTIC}
else
${RESTIC} self-update
fi
${RESTIC} version
# Check if repo exists
${RESTIC} snapshots || ${RESTIC} init
# Start backup
${RESTIC} -vv backup --one-file-system --exclude=/var/log/lastlog /
ENDSSH

47
bash/cronic.sh Normal file
View file

@ -0,0 +1,47 @@
#!/bin/bash
# Cronic v3 - cron job report wrapper
# Copyright 2007-2016 Chuck Houpt. No rights reserved, whatsoever.
# Public Domain CC0: http://creativecommons.org/publicdomain/zero/1.0/
set -eu
TMP=$(mktemp -d)
OUT=$TMP/cronic.out
ERR=$TMP/cronic.err
TRACE=$TMP/cronic.trace
set +e
"$@" >$OUT 2>$TRACE
RESULT=$?
set -e
PATTERN="^${PS4:0:1}\\+${PS4:1}"
if grep -aq "$PATTERN" $TRACE
then
! grep -av "$PATTERN" $TRACE > $ERR
else
ERR=$TRACE
fi
if [ $RESULT -ne 0 -o -s "$ERR" ]
then
echo "Cronic detected failure or error output for the command:"
echo "$@"
echo
echo "RESULT CODE: $RESULT"
echo
echo "ERROR OUTPUT:"
cat "$ERR"
echo
echo "STANDARD OUTPUT:"
cat "$OUT"
if [ $TRACE != $ERR ]
then
echo
echo "TRACE-ERROR OUTPUT:"
cat "$TRACE"
fi
fi
rm -rf "$TMP"

35
bash/dump.sh Normal file
View file

@ -0,0 +1,35 @@
#!/bin/sh
#===================================================================================
#
# FILE: dump.sh
# USAGE: dump.sh [-i interface] [tcpdump-parameters]
# DESCRIPTION: tcpdump on any interface and add the prefix [Interace:xy] in front of the dump data.
# OPTIONS: same as tcpdump
# REQUIREMENTS: tcpdump, sed, ifconfig, kill, awk, grep, posix regex matching
# BUGS: ---
# FIXED: - In 1.0 The parameter -w would not work without -i parameter as multiple tcpdumps are started.
# - In 1.1 VLAN's would not be shown if a single interface was dumped.
# - In 1.3 Some fixes for virtual interfaces have been provided by Reiner Keller. (Thanks!)
# NOTES: ---
# - 1.2 git initial
# AUTHOR: Sebastian Haas
# VERSION: 1.2
# CREATED: 16.09.2014
# REVISION: 22.09.2014
#
#===================================================================================
# When this exits, exit all background processes:
trap 'kill $(jobs -p) &> /dev/null && sleep 0.2 && echo ' EXIT
# Create one tcpdump output per interface and add an identifier to the beginning of each line:
if [[ $@ =~ -i[[:space:]]?[^[:space:]]+ ]]; then
tcpdump -l $@ | sed 's/^/[Interface:'"${BASH_REMATCH[0]:2}"'] /' &
else
for interface in $(ifconfig | grep '^[a-z0-9]' | awk '{print $1}'i | sed "/:[0-9]/d")
do
tcpdump -l -i $interface -nn $@ | sed 's/^/[Interface:'"$interface"'] /' 2>/dev/null &
done
fi
# wait .. until CTRL+C
wait

124
bash/dyndns-update.sh Normal file
View file

@ -0,0 +1,124 @@
#!/bin/bash
##
# dyndns-update update script
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
# default options
VER=4
SECRET=bx8qNQAnGic9OnFuqQu9XjG2NS9ed1fOaDds53R2jbq59m1WKWH3Rd1S3nijZ87u
ZONE=dyn.0l.de
HOST=$(hostname)
function usage {
cat <<-EOF
Usage: $0 [-4,-6] [-s SECRET] [-z ZONE] [-d] [-D] [HOST]
Options:
-s is the secret from the webservice otherwise prompted
-z nameserver zone
-4 update A record (default)
-6 update AAAA record
-D live monitor interface for changing addresses
-d enable verbose output
-h show this help
HOST is the hostname which you want to update
defaults to the local hostname
Example: $0 -6 -z dyn.0l.de sea
written by Steffen Vogel <post@steffenvogel.de>
EOF
}
function deps() {
FAILED=0
for DEP in $*; do
if ! which ${DEP} &>/dev/null; then
echo -e "This script requires ${DEP} to run but it is not installed."
((FAILED++))
fi
done
return ${FAILED}
}
function update() {
RDATA=$1
WAIT=1
URL="https://dyndns.k8s.0l.de/update?secret=${SECRET}&domain=${HOST}&addr=${RDATA}"
while true; do
if (( $DEBUG )); then echo "Updating record: ${URL}"; fi
CODE=$(curl -w %{http_code} -s -o /dev/stderr "${URL}") 2>&1
if [ ${CODE} -eq 0 ]; then
if (( ${DEBUG} )); then echo "Sleeping for ${WAIT} secs..."; fi
sleep ${WAIT} # wait until interface is ready
WAIT=$((${WAIT}*2))
elif [ ${CODE} -ge 500 ]; then
if (( ${DEBUG} )); then echo "Request failed. Aborting.."; fi
return 1
else
return 0
fi
done
}
function get() {
curl -${VER} -s http://ident.me
}
# check dependencies
if ! deps dig curl ip; then
echo -e "Unmet dependencies: Aborting!"
exit 1
fi
# parse arguments
while getopts "z:p:u:t:i:Dhd46" OPT; do
case ${OPT} in
s) SECRET=${OPTARG} ;;
4) VER=4 ;;
6) VER=6 ;;
D) DAEMON=1 ;;
z) ZONE=${OPTARG} ;;
d) DEBUG=${OPTARG:-5} ;;
h)
usage
exit 0 ;;
*)
usage
exit 1
esac
done
# clear all options and reset the command line
shift $((OPTIND-1))
# parsing host
if [ -n "$1" ]; then
HOST=$1
else
echo -e "missing host"
exit 1
fi
# prompting for secret
if [ -z "${SECRET}" ]; then
read -s -p "secret: " SECRET
echo
fi
IP=$(get)
if [ -n "${IP}" ]; then
update "${IP}" "${TYPE}" || exit
else
echo -e "failed to get ip from net"
exit 1
fi

70
bash/fan-ctl.sh Normal file
View file

@ -0,0 +1,70 @@
#!/usr/bin/env bash
# You'll need to enable IPMI over lan in idrac first
# iDRAC Settings -> Network -> IPMI Settings
# Channel Privilege Level Limit needs to be Administrator
# You may want to create a dedicated username/pass with IPMI permission in iDRAC Settings -> User Authentication
# See also: https://www.spxlabs.com/blog/2019/3/16/silence-your-dell-poweredge-server
IPMIHOST=169.254.0.1
IPMIUSER=root
IPMIPW=3LpnMcnY99cybeGM
IPMIEK=6055530028595864123105836429105276020000
FANSPEEDHEX=${1:-0x08} # See https://i.imgur.com/u1HMyqI.png
MAXTEMP=60
HYSTERESIS=5
FANFILE=/var/run/autofan
function ipmi() {
ipmitool -I lanplus -H "$IPMIHOST" -U "$IPMIUSER" -P "$IPMIPW" -y "$IPMIEK" $@
}
# For R710, which doesn't have cpu temps, try this line instead:
# if ! TEMPS=$(ipmi sdr type temperature | grep -i inlet | grep -Po '\d{2,3}' 2> /dev/null);
# thanks @bumbaclot
if ! TEMPS=$(ipmi sdr type temperature | grep -vi inlet | grep -vi exhaust | grep -Po '\d{2,3}' 2> /dev/null); then
echo "FAILED TO READ TEMPERATURE SENSOR!" >&2
logger -t "fanctl" -p user.err -i "Error: Could not read temperature sensor"
fi
HIGHTEMP=0
LOWTEMP=1
echo "Temps: ${TEMPS}"
for TEMP in $TEMPS; do
if [[ $TEMP > $MAXTEMP ]]; then
HIGHTEMP=1
fi
if [[ $TEMP > $(($MAXTEMP - $HYSTERESIS)) ]]; then
LOWTEMP=0
fi
done
if [[ -r "$FANFILE" ]]; then
AUTO=$(< "$FANFILE")
else
AUTO=1
fi
echo "Low: ${LOWTEMP}"
echo "High: ${HIGHTEMP}"
if [[ $HIGHTEMP == 1 ]]; then
# Automatic fan control
ipmi raw 0x30 0x30 0x01 0x01 >& /dev/null || echo "FAILED TO SET FAN CONTROL MODE" >&2; exit 1
echo "1" > "$FANFILE"
if [[ $AUTO == 0 ]]; then
logger -t "fanctl" -p user.info -i "Setting fan control to automatic"
fi
elif [[ $LOWTEMP == 1 ]]; then
# Manual fan control
ipmi raw 0x30 0x30 0x01 0x00 >& /dev/null || echo "FAILED TO SET FAN CONTROL SPEED" >&2
ipmi raw 0x30 0x30 0x02 0xff "$FANSPEEDHEX" >& /dev/null || echo "FAILED TO SET FAN SPEED" >&2
echo "0" > "$FANFILE"
if [[ $AUTO == 1 ]]; then
logger -t "fanctl" -p user.info -i "Setting fan control to manual"
fi
fi

29
bash/hetzer-sb-notify.sh Executable file
View file

@ -0,0 +1,29 @@
#!/bin/bash
##
# Scrape Hetzners Serverbörse for good deals
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
FILTER=$(mktemp)
cat > ${FILTER} <<EOF
.server | map(
select(
.hdd_size >= 3000 and
.ram >= 32 and
.bandwith >= 1000 and
.traffic == "unlimited" and
.cpu_benchmark >= 9000 and
(.setup_price | tonumber) == 0 and
(.price | tonumber) <= 50 and
(.specials | map(ascii_downcase ) | index("ssd"))
)
) |
sort_by(.price | tonumber) | reverse
EOF
curl https://www.hetzner.de/a_hz_serverboerse/live_data.json | jq -f $FILTER

23
bash/ip-rule-restore.sh Normal file
View file

@ -0,0 +1,23 @@
#!/bin/bash
GW_IF=bond0
for V in -4 -6; do
IPR="ip $V rule"
$IPR flush
ip $V route flush table default
if [ $V == -4 ]; then
ip $V route add 141.98.136.128/29 dev ${GW_IF} table default
ip $V route add default via 141.98.136.129 table default
else
ip $V route add 2a09:11c0:f0:bbf0::/64 dev ${GW_IF} table default
ip $V route add default via 2a09:11c0:f0:bbf0::1 dev ${GW_IF} src 2a09:11c0:f0:bbf0::3 table default
fi
$IPR add pref 200 not fwmark 0x1000 lookup main
$IPR add pref 240 not fwmark 0x1001 lookup dn42
$IPR add pref 250 lookup ebgp
$IPR add pref 300 lookup default
done

24
bash/luks-open.sh Normal file
View file

@ -0,0 +1,24 @@
#!/bin/bash
# Set IFS to a newline:
IFS="
"
for VOLUME in $(ls -1 /dev/vg*/*-luks); do
if ! cryptsetup isLuks ${VOLUME}; then
echo "${VOLUME} is not a luks device"
continue
fi
if [ -b /dev/disk/by-id/dm-uuid-*$(cryptsetup luksUUID ${VOLUME} | tr -d -)* ]; then
echo "${VOLUME} is opened"
else
NAME=$(basename -s '-luks' ${VOLUME})
cryptsetup luksOpen --allow-discards ${VOLUME} ${NAME}
# systemd-ask-password --id="zfs:$dataset" \
# "Enter passphrase for '$dataset':" | \
# zfs load-key "$dataset"
fi
done

47
bash/recursive-axfr.sh Normal file
View file

@ -0,0 +1,47 @@
#!/bin/bash
##
# Perform resursive AXFR queries to fetch all hostnames of a zone
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
print_hosts() {
ZONE=$1; shift 1
OPTS="$@"
SUBZONES=""
HOSTS=""
IFS=$'\n'
RECORDS=$(dig +nocmd $ZONE axfr +noall +answer ${OPTS})
for RECORD in ${RECORDS}; do
NAME=$(echo ${RECORD} | tr -s '\t ' '\t' | cut -f1)
TYPE=$(echo ${RECORD} | tr -s '\t ' '\t' | cut -f4)
if [ -z "${NAME}" -o "${NAME}" == *'*'* ]; then
continue
fi
case ${TYPE} in
NS) SUBZONES="${SUBZONES} ${NAME}" ;;
A|AAAA|CNAME) HOSTS="${NAME} ${HOSTS}" ;;
esac
done
UNIQUE_SUBZONES=$(echo ${SUBZONES} | tr ' ' '\n' | sort -u)
for SUBZONE in ${UNIQUE_SUBZONES}; do
if [ ${SUBZONE} != ${ZONE} ]; then
HOSTS="$(print_hosts ${SUBZONE}) ${HOSTS}"
fi
done
UNIQUE_HOSTS=$(echo ${HOSTS} | tr ' ' '\n' | sort -u)
for HOST in ${UNIQUE_HOSTS}; do
echo ${HOST%.}
done
}
print_hosts $@

View file

@ -0,0 +1,46 @@
#!/bin/bash
##
# Convert BTRFS snapshots to Restic Snapshots
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
PARENT=""
HOST=$1
AFTER=$(date -d"$2" +%s)
for SNAP in $(ls -1); do
D=$(echo $SNAP | cut -d_ -f1)
T=$(echo $SNAP | cut -d_ -f2 | tr - :)
W=$(date -d "$D $T" +%u)
if [ -z "$D" -o -z "$T" -o -z "$W" ]; then
echo "Failed to parse: $SNAP"
break
fi
if [ -n "$PARENT" ]; then
RESTIC_OPTS="--parent $PARENT"
else
RESTIC_OPTS=""
fi
if [ "$W" != "7" ]; then continue; fi
echo $SNAP
continue
UNIX=$(date -d"$D $T" +%s)
if (( $UNIX < $AFTER )); then continue; fi
pushd $SNAP
restic backup $RESTIC_OPTS --tag old_btrfs_snapshot --host $HOST --time "$D $T" --ignore-inode .
popd
PARENT=$(restic snapshots --tag old_btrfs_snapshot --host $HOST --last --json | jq -r .[0].id)
done

118
bash/smart-read.sh Normal file
View file

@ -0,0 +1,118 @@
#!/bin/bash
# Copyright (c) 2020 Manuel Pitz
#
# Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
# http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
# http://opensource.org/licenses/MIT>, at your option. This file may not be
# copied, modified, or distributed except according to those terms.
DEBUG=0
handle_Type () {
local vendor=$1
local attrName=$2
local data=$3[@]
temp=`grep "$attrName" <<< "$data" | sed "s/^[ \t]*//" | tr -s ' ' | cut -d" " -f10 | sed "s/^[ \t]*//"`
echo $temp
}
handle_singleCol () {
local vendor=$1
local attrName=$2
local data=$3[@]
temp=`grep "$attrName" <<< "$data" | sed "s/^[ \t]*//" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
echo $temp
}
handle_SATA_HDD () {
local vendor=$1
local driveData=$2[@]
temp=$(handle_Type $vendor "Temperature_Celsius" "$driveData")
seek_err=$(handle_Type $vendor "Seek_Error_Rate" "$driveData")
read_err=$(handle_Type $vendor "Raw_Read_Error_Rate" "$driveData")
power_on=$(handle_Type $vendor "Power_On_Hours" "$driveData")
status=$(handle_singleCol $vendor "SMART overall-health self-assessment test result:" "$driveData")
printf "%10s %10s %20s %20s %10s %10s %10s %10s %10s\n" $path "$vendor" "$driveModel" "$driveSerial" "$temp" "$seek_err" "$read_err" "$power_on" "$status"
}
handle_SAS_HDD () {
local vendor=$1
local driveData=$2[@]
if [ $DEBUG == 1 ]; then
echo "SAS handle"
fi
temp=`grep "Drive Temperature:" <<< "$driveData" | tr -s ' ' | cut -d" " -f4 | sed "s/^[ \t]*//"`
readCorrected=`grep "read:" <<< "$driveData" | tr -s ' ' | cut -d" " -f5 | sed "s/^[ \t]*//"`
readunCorrected=`grep "read:" <<< "$driveData" | tr -s ' ' | cut -d" " -f8 | sed "s/^[ \t]*//"`
writeCorrected=`grep "write:" <<< "$driveData" | tr -s ' ' | cut -d" " -f5 | sed "s/^[ \t]*//"`
writeunCorrected=`grep "write:" <<< "$driveData" | tr -s ' ' | cut -d" " -f8 | sed "s/^[ \t]*//"`
seek_err=$(handle_Type $vendor "Seek_Error_Rate" "$driveData")
read_err=$(($readCorrected + $readunCorrected + $writeCorrected + $writeunCorrected))
power_on=$(handle_Type $vendor "Power_On_Hours" "$driveData")
status=$(handle_singleCol $vendor "Status:" "$driveData")
printf "%10s %10s %20s %20s %10s %10s %10s %10s %10s\n" $path "$vendor" "$driveModel" "$driveSerial" "$temp" "$seek_err" "$read_err" "$power_on" "$status"
}
echo "readSmartData"
mapfile -t DRIVES < <(smartctl --scan)
printf "%10s %10s %20s %20s %10s %10s %10s %10s %10s\n" "Path" "Vendor" "Model" "Serial" "Temp" "Seek_err" "Read_err" "Power_on" "Status"
for drive in "${DRIVES[@]}"
do
path=`cut -d" " -f1 <<< "$drive"`
devType=`cut -d" " -f6 <<< "$drive"`
if [ $path == "/dev/bus/0" ]; then continue; fi
driveData=`smartctl -a $path`
driveFamily=`grep "Model Family:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
driveVendor=`grep "Vendor:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
driveModel=`grep "Device Model:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
driveSerial=`grep "Serial Number:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
if [ -z "$driveSerial" ]; then
driveSerial=`grep "Serial number:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
fi
if [ -z "$driveModel" ]; then
driveModel=`grep "Product:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
fi
#echo $driveName
if [ -n "$driveVendor" ]; then
vendor=$driveVendor
elif [ -z "$driveFamily" ]; then
vendor=`cut -d" " -f1 <<< "$driveModel"`
else
vendor=`cut -d" " -f1 <<< "$driveFamily"`
fi
tmpModel=`cut -d" " -f2 <<< "$driveModel"`
if [ -n "$tmpModel" ]; then
driveModel=$tmpModel
fi
if [[ $vendor == *"Seagate"* ]]; then
#echo "rerun smartctl for Seagate drives"
driveData=`smartctl -a -v 7,raw48:54 -v 1,raw48:54 $path`
fi
sasFlag=`grep "Transport protocol:" <<< "$driveData" | tr -s ' ' | cut -d":" -f2 | sed "s/^[ \t]*//"`
if [[ $sasFlag == *"SAS"* ]]; then
handle_SAS_HDD $vendor "$driveData"
else
handle_SATA_HDD $vendor "$driveData"
fi
done

16
bash/update-roa.sh Normal file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
# Update ROA tables for DN42
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
set +x
curl -sfSLR {-o,-z}/var/lib/bird/bird_roa_dn42_v4.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf
curl -sfSLR {-o,-z}/var/lib/bird/bird_roa_dn42_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf
birdc configure

15
bash/update-xmltv.sh Normal file
View file

@ -0,0 +1,15 @@
#!/bin/bash
##
# Update XMLTV data between Emby and TVHeadEnd
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
tv_grab_eu_epgdata --output /srv/Data/Emby/epgdata.xml
tv_grab_eu_xmltvse --output /srv/Data/Emby/xmltvse.xml
cat /srv/Data/Emby/epgdata.xml | socat - UNIX-CONNECT:/var/lib/tvheadend/config/epggrab/xmltv.sock
cat /srv/Data/Emby/xmltvse.xml | socat - UNIX-CONNECT:/var/lib/tvheadend/config/epggrab/xmltv.sock

13
bash/virsh-start-all.sh Normal file
View file

@ -0,0 +1,13 @@
#!/bin/bash
##
# Start all libvirt VMs
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
for VM in $(virsh list --inactive --name); do
virsh start ${VM}
done

25
bash/zfs-load-keys.sh Normal file
View file

@ -0,0 +1,25 @@
#!/bin/bash
##
# Load ZFS encryption keys
#
# @copyright 2021, Steffen Vogel
# @license http://www.gnu.org/licenses/gpl.txt GNU Public License
# @author Steffen Vogel <post@steffenvogel.de>
# @link http://www.steffenvogel.de
##
# Set IFS to a newline:
IFS="
"
for dataset in $(zfs list -H -p -o name,encryptionroot | \
awk -F "\t" '{if ($1 == $2) { print $1 }}')
do
if [ "$(zfs get -H -p -o value keylocation "$dataset")" = "prompt" ] &&
[ "$(zfs get -H -p -o value keystatus "$dataset")" = "unavailable" ]
then
systemd-ask-password --id="zfs:$dataset" \
"Enter passphrase for '$dataset':" | \
zfs load-key "$dataset"
fi
done