From 535c2a093d5c72c6677a6ff06c7208beca3670b9 Mon Sep 17 00:00:00 2001 From: "root@6core" Date: Sun, 13 Apr 2025 16:14:17 +0200 Subject: [PATCH] Update 2025-04-13_16:14:16 --- gitea_push.sh | 219 +++++++++++++++++++++++++++++++++++++++++++ postfix_setup.sh | 68 ++++++++++++++ sendmail_test.sh | 47 ++++++++++ test_script.sh | 2 + update_fancontrol.sh | 31 ++++++ z_aliases_stats.sh | 107 +++++++++++++++++++++ 6 files changed, 474 insertions(+) create mode 100755 gitea_push.sh create mode 100755 postfix_setup.sh create mode 100755 sendmail_test.sh create mode 100755 test_script.sh create mode 100755 update_fancontrol.sh create mode 100755 z_aliases_stats.sh diff --git a/gitea_push.sh b/gitea_push.sh new file mode 100755 index 0000000..0bca28e --- /dev/null +++ b/gitea_push.sh @@ -0,0 +1,219 @@ +#!/bin/zsh +# Script Version: 1.5 +# Description: Pushes the current folder (e.g. /etc) to a nested Gitea repo using provided nesting arguments. Auto-creates the remote repo via Gitea API if missing. + +# Set variables +# ======== + +# Try to extract GITEA_API_TOKEN from ~/.gitea_token if not set +if [ -z "$GITEA_API_TOKEN" ] && [ -f "$HOME/.gitea_token" ]; then + GITEA_API_TOKEN=$(<"$HOME/.gitea_token") + export GITEA_API_TOKEN +fi + +GITEA_USER=$(awk '{for(i=1;i<=NF;i++) if($i=="login") print $(i+1)}' ~/.netrc | head -n1) +if [ -z "$GITEA_USER" ]; then + echo "[ERROR] No login found in ~/.netrc" + exit 1 +fi + +GITEA_URL="https://$(awk '{for(i=1;i<=NF;i++) if($i=="machine") print $(i+1)}' ~/.netrc | head -n1)" +if [ -z "$GITEA_URL" ]; then + echo "[ERROR] No URL found in ~/.netrc" + exit 1 +fi +GITEA_API_URL="$GITEA_URL/api/v1" + +PRIVATE=false +DEBUG=false +COMMIT_MESSAGE="Update $(date +"%F_%T")" + +# Logging function +# ======== +log() { + local level="$1"; shift + if [[ "$level" == "DEBUG" && "$DEBUG" != true ]]; then return; fi + local color_reset="$(tput sgr0)" + local color="" + case "$level" in + INFO) color="$(tput setaf 2)" ;; # green + WARNING) color="$(tput setaf 3)" ;; # yellow + ERROR) color="$(tput setaf 1)" ;; # red + DEBUG) color="$(tput setaf 4)" ;; # blue + esac + echo "${color}[$level] $*${color_reset}" +} + +# Functions +# ======== +create_repo() { + log INFO "Repository does not exist. Creating via API: $REMOTE_PATH" + log DEBUG "POST $GITEA_API_URL/user/repos with name=$REMOTE_PATH and private=$PRIVATE" + RESPONSE=$(curl -s -X POST \ + -H "Authorization: token $GITEA_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"name\": \"$FOLDER_NAME\", \"private\": $PRIVATE}" \ + "$GITEA_API_URL/user/repos") + + if echo "$RESPONSE" | grep -q '"clone_url"'; then + log INFO "Remote repository created successfully." + HTTP_STATUS=200 + else + log ERROR "Failed to create remote repository: $RESPONSE" + exit 1 + fi +} + +prepare_commit() { + git add . + if git diff --quiet HEAD && ! git rev-parse --verify HEAD >/dev/null 2>&1; then + log INFO "Creating initial commit" + git commit -m "$COMMIT_MESSAGE" + elif ! git diff --quiet HEAD; then + log INFO "Committing changes" + git commit -m "$COMMIT_MESSAGE" + else + log INFO "Nothing to commit" + fi +} + +setup_remote() { + if git remote | grep -q '^origin$'; then + log INFO "Updating remote origin URL" + git remote set-url origin "$GIT_REMOTE" + else + log INFO "Adding remote origin" + git remote add origin "$GIT_REMOTE" + fi +} + +push_changes() { + log INFO "Pushing to $GIT_REMOTE" + git push -u origin main +} + +# Show help if no arguments are given +# ======== +if [ $# -eq 0 ]; then + echo "GITEA_API_TOKEN=" + echo "Usage: $0 [--private] [--debug] [--message \"your commit message\"] " + echo "Example: $0 server" + echo " $0 --private workstation" + echo " $0 --debug server" + echo " $0 --message \"minor update\" server" + echo + echo "Note: You must cd into the target folder before running this script." + echo "For example:" + echo " cd /etc && $0 server" + echo + echo "Authentication:" + echo " Git operations (clone, push, pull) use ~/.netrc with your Git password:" + echo " machine \$(echo \"$GITEA_URL\" | sed 's|https\?://||') login $GITEA_USER password \"\"" + echo " chmod 600 ~/.netrc" + echo + echo " API operations (e.g. creating repos) use a Personal Access Token stored in ~/.gitea_token" + echo " echo \"\" > ~/.gitea_token && chmod 600 ~/.gitea_token" + exit 0 +fi + +# Parse arguments +# ======== +POSITIONAL_ARGS=() +while [[ $# -gt 0 ]]; do + case "$1" in + --private) + PRIVATE=true + shift + ;; + --debug) + DEBUG=true + shift + ;; + --message) + COMMIT_MESSAGE="$2" + shift 2 + ;; + *) + POSITIONAL_ARGS+=("$1") + shift + ;; + esac +done + +set -- "${POSITIONAL_ARGS[@]}" + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 [--private] [--debug] [--message \"your commit message\"] " + exit 1 +fi + +HOST_GROUP=$(echo "$1" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-') +HOST_NAME=$(hostname -s | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-') +FOLDER_NAME="${HOST_NAME}-${HOST_GROUP}-$(basename "$PWD")" +REPO_PATH="$PWD" +REMOTE_PATH="$FOLDER_NAME" +GIT_REMOTE="$GITEA_URL/$GITEA_USER/$FOLDER_NAME.git" + +# Git authentication hint +log DEBUG "Ensure ~/.netrc has: machine login $GITEA_USER password " + +# Check or create remote repo +check_or_create_repo() { + if [ -z "$GITEA_API_TOKEN" ]; then + log WARNING "GITEA_API_TOKEN is not set. Skipping API repo creation." + return + fi + + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: token $GITEA_API_TOKEN" \ + "$GITEA_API_URL/repos/$GITEA_USER/$FOLDER_NAME") + + if [ "$HTTP_STATUS" -ne 200 ]; then + create_repo + else + log INFO "Remote repository already exists." + fi +} + + +check_or_create_repo + +# Main Process +# ======== + +# Safety check against pushing from / or $HOME +if [[ "$PWD" == "$HOME" || "$PWD" == "/" ]]; then + log ERROR "Refusing to run inside \$PWD=$PWD" + exit 1 +fi +log INFO "Pushing $REPO_PATH to $GIT_REMOTE" +cd "$REPO_PATH" || { log ERROR "Directory $REPO_PATH not found"; exit 1; } + +# Initialize git if needed +# Branch is fixed to 'main' for simplicity and consistency +if [ ! -d .git ]; then + log INFO "Initializing Git repo" + git init + git config init.defaultBranch main + git checkout -b main +else + log DEBUG ".git directory already present" +fi + +# Ensure at least one commit exists +prepare_commit + +# Set or update remote +if [ "$HTTP_STATUS" -eq 200 ]; then + setup_remote +else + log WARNING "Skipping remote setup – repository does not exist." +fi + +# Push to remote +if [ "$HTTP_STATUS" -eq 200 ]; then + push_changes +else + log WARNING "Skipping push – repository does not exist." +fi + diff --git a/postfix_setup.sh b/postfix_setup.sh new file mode 100755 index 0000000..a9cb2e7 --- /dev/null +++ b/postfix_setup.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# Script Version: 0.9 +# Description: Check if Postfix is installed before proceeding with installation + +# Validate hostname before proceeding +if [ "$(hostname)" == "$(hostname --fqdn)" ]; then + echo "Error: Hostname and fully qualified domain name must differ." + exit 1 +fi + +# Variables +# ======== +POSTFIX_MAIN_CF=/etc/postfix/main.cf +SASL_PASSWD_FILE=/etc/postfix/sasl_passwd +SMTP_SERVER="mail.bubuit.net" +SMTP_PORT="587" +SMTP_USER="srvlogz" +SMTP_PASS="Id(Z]GtSty2S" +RECIPIENT="srvlogz@bubuit.net" +TEST_RECIPIENT="root" +MAILNAME=$(hostname --fqdn) +ALIASES_FILE="/etc/aliases" + +# Check if Postfix is already installed +if dpkg -l | grep -q "^ii postfix "; then + echo "Postfix is already installed. Skipping installation." +else + # Preconfigure Postfix installation + debconf-set-selections <<< "postfix postfix/mailname string $MAILNAME" + debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local only'" + + # Install required packages non-interactively + apt update + apt install -y postfix libsasl2-modules mailutils +fi + +# Configure Postfix for SMTP relay (only necessary changes) +postconf -e "relayhost = $SMTP_SERVER:$SMTP_PORT" +postconf -e "smtp_tls_security_level = may" +postconf -e "smtp_sasl_auth_enable = yes" +postconf -e "smtp_sasl_password_maps = hash:$SASL_PASSWD_FILE" +postconf -e "smtp_sasl_security_options = noanonymous" + +# Store SMTP credentials +printf "$SMTP_SERVER:$SMTP_PORT $SMTP_USER:$SMTP_PASS\n" > $SASL_PASSWD_FILE +chmod 600 $SASL_PASSWD_FILE +postmap $SASL_PASSWD_FILE + +# Update /etc/aliases +if [ -n "$RECIPIENT" ] && ! grep -q "^root: " $ALIASES_FILE; then + echo "root: $RECIPIENT" >> $ALIASES_FILE + newaliases +else + echo "Alias for root already exists, skipping update." +fi +newaliases + +# Reloading Postfix configuration +systemctl reload postfix + +# Test email sending +echo "Test email from Postfix SMTP relay" | mail -s "Test Subject" root + +# Verify logs +# Check mail logs using: tail -f /var/log/mail.log + +# Postfix setup and test email completed + diff --git a/sendmail_test.sh b/sendmail_test.sh new file mode 100755 index 0000000..33bf783 --- /dev/null +++ b/sendmail_test.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Script Name: sendmail_test.sh +# Version: 02 +# Description: This script sends a test email using sendmail. The recipient's email address is the first argument. + +# Check if an argument (email address) is provided +if [ -z "$1" ]; then + TO="root" +else + TO="$1" +fi + +# Email details +SUBJECT="Postfix Test" +FROM="noreply@$(hostname)" +BODY="This is the email body!" + +# Function to send email +send_email() { + if ! command -v sendmail &> /dev/null; then + echo "Sendmail is not installed or configured. Please ensure sendmail is installed and properly set up." >&2 + exit 1 + fi + + sendmail -t </dev/null; then + echo "[WARNING] Konnte .zshrc nicht laden - verwende nur History-Daten" +fi + +# Aliase mit Definitionen erfassen (nur a berücksichtigen) +typeset -A ALIAS_DEFS +for line in "${(@f)$(alias -L)}"; do + if [[ $line =~ ^alias\ ([^=]+)=[\'\"]?(.*)[\'\"]?$ ]]; then + name=${match[1]} + def=${match[2]} + # Nur Alias "a" speichern + if [[ $name == "a" ]]; then + ALIAS_DEFS[$name]=$def + fi + fi +done + +# Alias-Namen als Array (nur a) +ALIASES=("a") + +# Falls keine Aliase vorhanden sind, abbrechen +if [[ ${#ALIASES[@]} -eq 0 ]]; then + echo "[ERROR] Kein Alias 'a' gefunden." + exit 1 +fi + +# Alias-Pattern erstellen (nur für a) +ALIAS_PATTERN="^a(;|[ \t\n]|$)" + +# Debug-Ausgabe +echo "[DEBUG] Gefundene Aliase: ${(kv)ALIAS_DEFS}" +echo "[DEBUG] Verwendetes Alias-Pattern: $ALIAS_PATTERN" + +# History analysieren mit LC_ALL=C für konsistente Kodierung +LC_ALL=C awk -F';' -v aliases="$ALIAS_PATTERN" -v alias_defs="${(j:||:)${(kv)ALIAS_DEFS}}" ' +BEGIN { + invalid_lines = 0 + # Alias-Definitionen parsen + if (alias_defs != "") { + n = split(alias_defs, pairs, "||") + for (i = 1; i <= n; i += 2) { + DEFINITIONS[pairs[i]] = pairs[i+1] + } + } +} +{ + if (NF < 2 || $1 !~ /^:[ 0-9]+:[0-9]+$/) { + invalid_lines++ + next + } + + cmd = substr($0, index($0, ";") + 1) + sub(/^[ \t]+/, "", cmd) + sub(/[ \t]+$/, "", cmd) + + if (cmd == "") { + invalid_lines++ + next + } + + if (cmd ~ aliases) { + split(cmd, words, /[ \t;]/) + alias_name = words[1] + if (alias_name == "a") { # Nur a zählen + if (alias_name in CMD) { + CMD[alias_name]++ + } else { + CMD[alias_name] = 1 + } + count++ + } + } +} +END { + if (invalid_lines > 0) { + print "[WARNING] Ignorierte " invalid_lines " ungültige History-Einträge" > "/dev/stderr" + } + if (count > 0) { + for (a in CMD) { + def = (a in DEFINITIONS) ? DEFINITIONS[a] : "undefined" + print CMD[a], CMD[a]*100/count "%", a "=" def + } + } else { + print "[ERROR] Keine Aufrufe von a in der History gefunden" > "/dev/stderr" + exit 1 + } +}' "$HISTORY_FILE" | sort -nr | head -n "$N" | column -c4 -s " " -t | nl || { + echo "[ERROR] Fehler bei der Verarbeitung der History-Datei" + exit 1 +}