AWS : Mount eines S3 Buckets unter Debian

Installation des benötigten Packetes auf der Debian Kiste.
apt install s3fs
Erstellen einer Passwort Datei im Home Directory
touch ~/.passwd-s3fs
echo "accessKeyId:secretAccessKey" > ~/.passwd-s3fs
Wenn mehrere Amazon S3 Buckets verwendet werden müssen kann auch der Name des Buckets vor den Zugangsdaten hinzugefügt werden.
echo "bucketName:accessKeyId:secretAccessKey" > ~/.passwd-s3fs
Da hier sensible Zugangsdaten in der Datei stehen müssen die Rechte auf 600 geändert werden !
chmod 600 ~/.passwd-s3fs
Wenn alles richtig ist kann das Amazon S3 Buckets gemountet werden
s3fs [BUCKET-NAME] [MOUNT-POINT]
Der Eintrag für /etc/fstab sieht dann so aus, hier ist debug noch aktiv. Das sollte für einen Betrieb in der Produktion deaktiviert werden.
# MOUNT S3 MIT DEBUG
[BUCKET-NAME] [MOUNTPOINT] fuse.s3fs _netdev,allow_other,dbglevel=dbg,curldbg 0 0
# MOUNT S3 OHNE DEBUG
[BUCKET-NAME] [MOUNTPOINT] fuse.s3fs _netdev,allow_other 0 0

Quellen :
https://cloud.netapp.com/blog/amazon-s3-as-a-file-system
https://github.com/s3fs-fuse/s3fs-fuse/wiki/Fuse-Over-Amazon

Debian 9 : hohe CPU Last durch systemd-journald

Problem : Ein Server mit Debian 9 hat eine durchgehend hohe Systemlast. Beim prüfen der Last fällt auf das "systemd-journald" der Grund ist. Nachdem ich mit journalctl -xe nachgeschaut habe woran das liegen könnte sind mir die folgenden Zeilen aufgefallen die sich immer wieder wiederholen.
Sep 08 14:33:27 HOSTNAME sh[293]: /sbin/dhclient-script: 28: .: Can't open /usr/share/sendmail/dynamic
Sep 08 14:33:27 HOSTNAME dhclient[302]: DHCPDECLINE on eth0 to 255.255.255.255 port 67
Sep 08 14:33:27 HOSTNAME sh[293]: DHCPDECLINE on eth0 to 255.255.255.255 port 67
Sep 08 14:33:27 HOSTNAME sh[293]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5
Sep 08 14:33:27 HOSTNAME dhclient[302]: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5
Sep 08 14:33:27 HOSTNAME dhclient[302]: DHCPREQUEST of XXX.XXX.XXX.XXX on eth0 to 255.255.255.255 port 67
Sep 08 14:33:27 HOSTNAME sh[293]: DHCPREQUEST of XXX.XXX.XXX.XXX on eth0 to 255.255.255.255 port 67
Sep 08 14:33:27 HOSTNAME sh[293]: DHCPOFFER of XXX.XXX.XXX.XXX from XXX.XXX.XXX.XXX
Sep 08 14:33:27 HOSTNAME dhclient[302]: DHCPOFFER of XXX.XXX.XXX.XXX from XXX.XXX.XXX.XXX
Sep 08 14:33:27 HOSTNAME sh[293]: DHCPACK of XXX.XXX.XXX.XXX from XXX.XXX.XXX.XXX
Sep 08 14:33:27 HOSTNAME dhclient[302]: DHCPACK of XXX.XXX.XXX.XXX from XXX.XXX.XXX.XXX
Sep 08 14:33:27 HOSTNAME sh[293]: RTNETLINK answers: File exists

Der Grund für den andauernden Neustart Wahn des dhclient war diese Zeile
Sep 08 14:33:27 HOSTNAME sh[293]: /sbin/dhclient-script: 28: .: Can't open /usr/share/sendmail/dynamic
Lösung : In meinem Fall lief ein Skript Amok.
/etc/dhcp/dhclient-exit-hooks.d/sendmail
Da ich hier sowieso auf eine andere Art der Überwachung setzte hab ich das Skript einfach mit folgenden Befehl gelöscht
rm /etc/dhcp/dhclient-exit-hooks.d/sendmail
seitdem ist die Systemlast wieder auf dem gewohnten Stand unterwegs. Wenn man das allerdings benötigt kann man auch diesen Befehl in den Terminal hämmern.
mkdir -p /usr/share/sendmail && touch /usr/share/sendmail/dynamic

AWS : automatisierter start der aws instanzen

Problem : Automatisches Starten der Instanzen bei AWS
Lösung : Man lässt dieses Skript auf einer Maschine/Instanz laufen auf der die aws cli konfiguriert ist.
#!/bin/bash
set -o nounset
set -o pipefail
# Script startet alle definierten Maschinen
AWS_PATH="/root/.local/bin/"
# -----------------------------------------------------------
# Definieren der Maschinen die gestartet werden müssen
# -----------------------------------------------------------
# z.B. declare -a TO_START=("i-xxxxxxxxxxxxxxxxx" "i-xxxxxxxxxxxxxxxxx" "i-xxxxxxxxxxxxxxxxx" "i-xxxxxxxxxxxxxxxxx")
declare -a TO_START=("")
# ------------------------------------------------------------
# nichts mehr ändern
# ------------------------------------------------------------
LOG_PATH="$(dirname $(readlink -f $0))/logs"
LOG_FILE="$(date +%Y%m%d)-awscli.log"
# ------------------------------------------------------------
# Funktionen
# ------------------------------------------------------------
function logger () {
        mkdir -p ${LOG_PATH}
        if [ -z ${2} ]; then
                STATI="INFO"
        else
                STATI="${2}"
        fi
        echo "$(date +%Y-%m-%d) | $(date +%R) | ${STATI} | ${1}" >> ${LOG_PATH}/${LOG_FILE}
}
# ------------------------------------------------------------
logger "Starte -> ${0##*/}" "INFO"
cnt=${#TO_START[@]}
for ((i = 0 ; i < cnt ; i++ )); do
        logger "${TO_START[i]} wird gestartet" "INFO"
        ${AWS_PATH}aws ec2 start-instances --instance-ids ${TO_START[i]} > /dev/null 2>&1
done
logger "Beende -> ${0##*/}" "INFO"
exit 0

AWS : automatisierter shutdown der aws instanzen

Problem : Man hat ein paar Instanzen in der AWS installiert, diese werden aber nur für die Entwicklung bzw. Tests benötigt. Um zusätzliche Kosten zu sparen kann man diese automatisiert außerhalb der benötigten Zeiten herunterfahren.

Lösung : Man lässt dieses Skript auf einer Maschine/Instanz laufen auf der die aws cli konfiguriert ist. Das Beispiel hier läuft selbst eine AWS Instanz. Aus diesem Grund wird mit
OWN_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
die eigene ID ermittelt.
Das Skript fährt alle Instanzen herunter außer diese die in DO_NOT_SHUTDOWN definiert sind.

#!/bin/bash
# ----------------------------------
set -o nounset
set -o pipefail
# ----------------------------------
#
# Script fährt alle Instanzen herunter bis auf die unter DO_NOT_SHUTDOWN definierten
# die eigene Maschine bleibt natürlich auch online
# PFAD zu awscli
AWS_PATH="/root/.local/bin/"
OWN_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
# -----------------------------------------------------------
# Definieren der Maschinen die NICHT heruntergefahren werden
# -----------------------------------------------------------
# wenn die eigene Instanz geschützt werden soll diese mit ins Array aufnehmen. Nur so ist gewährleistet das alles abgearbeitet wird
# z.B. declare -a DO_NOT_SHUTDOWN=("${OWN_INSTANCE_ID}" "i-xxxxxxxxxxxxx" "i-xxxxxxxxxxxxx" "i-xxxxxxxxxxxxx")
#
declare -a DO_NOT_SHUTDOWN=("${OWN_INSTANCE_ID}")
# -----------------------------------------------------------
# nichts mehr ändern
# -----------------------------------------------------------
LOG_PATH="$(dirname $(readlink -f $0))/logs"
LOG_FILE="$(date +%Y%m%d)-awscli.log"
# -----------------------------------------------------------
# Funktionen
# -----------------------------------------------------------
function is_inList ()
{
  SERVER=${1}
  max=${#DO_NOT_SHUTDOWN[@]}
  RET=1

  for ((i = 0 ; i < max ; i++ )); do
    if [ "${DO_NOT_SHUTDOWN[i]}" = "${SERVER}" ]; then
      RET=0
      break
    fi
  done

  return $RET
}
function logger () {
        mkdir -p ${LOG_PATH}
        if [ -z ${2} ]; then
                STATI="INFO"
        else
                STATI="${2}"
        fi
        echo "$(date +%Y-%m-%d) | $(date +%R) | ${STATI} | ${1}" >> ${LOG_PATH}/${LOG_FILE}
}
# -----------------------------------------------------------
# Prüfen ob OWN_INSTANCE_ID einen Wert enthält
# -----------------------------------------------------------
logger "Starte -> ${0##*/}" "INFO"
if [ -z ${OWN_INSTANCE_ID} ]; then
        logger "OWN_INSTANCE_ID ist leer Skript wird nicht gestartet" "ERROR"
        logger "Beende AWS Script" "ERROR"
        exit 99
fi

for item in $(${AWS_PATH}aws ec2 describe-instances --query 'Reservations[].Instances[][InstanceId,Tags[?Key==`Name`].Value | [0],LaunchTime,State.Name]' --filters "Name=instance-state-name,Values=running" --output text | awk '{print $1}')
do
        is_inList ${item}
        RET=$?
        if [ $RET -eq 0 ]; then
                logger "${item} wird nicht heruntergefahren definiert in OWN_INSTANCE_ID oder DO_NOT_SHUTDOWN" "INFO"
                continue
        else
                logger "${item} wird heruntergerfahren" "INFO"
                #----  aws cli fährt kiste herunter
                ${AWS_PATH}aws ec2 stop-instances --instance-ids ${item} > /dev/null 2>&1
        fi
done
logger "Beende -> ${0##*/}" "INFO"
exit 0


Bash : Funktion um Files zu laden

Funktion um Dateien aus dem Internet zu laden. Prüft ob curl vorhanden ist , wenn nicht wird wget versucht. Wenn gar nichts von beiden gefunden wird wird das Skript beendet.

function get_remote_file () {
        # ------------------------- get_remote_file -------------------------------------------------------------------
        # download an file to local storage
        #
        # need 2 parameters : get_remote_file [URL_TO_FILE] [LOCAL_PATH]
        # -----------------------------------------------------------------------------------------------------------------

        if [[ ! -z "${1}" || ! -z "${2}" ]]; then
                bin_dl=""
                # check Local Path
                if [ ! -d "${2}" ]; then
                        mkdir "${2}"
                fi
                # check bins
                # using command instead of which to be posix comp.
		
		# ------ check curl
                command -v curl >/dev/null 2>&1
                if [ $? -eq 0 ]; then
                        bin_dl="curl -s -O "
                fi

		# ------ check wget
                command -v wget >/dev/null 2>&1
                if [[ ${bin_dl} = "" && $? -eq 0 ]]; then
                        bin_dl="wget -q "
                fi

		# ------ if emtpy curl and wget not found
                if [ ${bin_dl} = "" ]; then
                        echo "need curl or wget for work please install one of them"
                        exit 98
                fi

                # download file
                if [[ "${1}" =~ http:// || "${1}" =~ https:// || "${1}" =~ ftp:// ]]; then
                        # ${1} is an remote file will be downloaded to ${2}
                        cd "${2}" && { ${bin_dl} "${1}" ; cd -; }
                else
                        # ${1} is not an remote file EXIT !
                        exit 98
                fi
        else
                echo "check parameters for function #> get_remote_file"
                exit 9
        fi
}

Bash : Inhalt von ZIP Dateien vergleichen

Problem : Man möchte über Bash nur den Inhalt einer Zip Datei vergleichen. Die Zip Datei wird aber automatisiert auf einem Server über cron erstellt, was zur Folge hatte das der Zeitstempel und somit auch die md5 Summen unterschiedlich sind.

Lösung : Die Lösung ist mit unzip in die Datei zu schauen und diesen Output mit diff zu verleichen.
function check_files_in_zip () {
	# ------------------------ check_files_in_zip ---------------------------------------
	# compare the content of two zipfiles if equal the function return 0 otherwise 1 
	#
	# need 2 parameters : check_files_in_zip [NAME_OF_OLD_ZIPFILE] [NAME_OF_NEW_ZIPFILE]
	# -----------------------------------------------------------------------------------

	if [[ ! -z "${1}" || ! -z "${2}"  ]]; then
        	diff <(unzip -v -l "${1}" | awk '! /Archiv/ && /[0-9]/ { print $1,$5,$6,$7,$8 }' | sed '$d') <(unzip -v -l "${2}" | awk '! /Archiv/ && /[0-9]/ { print $1,$5,$6,$7,$8 }' | sed '$d') 1>/dev/null 2>&1
        	if [ $? -eq 0 ]; then
                	return 0
        	else
                	return 1
       		fi
	else
		echo "check parameters for function #> check_files_in_zip"
                exit 9
        fi
}
“Das einzig sichere System müsste ausgeschaltet, in einem versiegelten und von Stahlbeton ummantelten Raum und von bewaffneten Schutztruppen umstellt sein.”
Gene Spafford (Sicherheitsexperte)