diff --git a/SysInfoProject/BACKUP_Things/README.md b/SysInfoProject/BACKUP_Things/README.md new file mode 100644 index 0000000..48f8a6c --- /dev/null +++ b/SysInfoProject/BACKUP_Things/README.md @@ -0,0 +1,115 @@ +```bash +cat << 'EOF' > README.md +# Smart Backup & Restore Tool + +A versatile, hybrid Bash script for Linux that handles directory backups and restorations. It supports both a user-friendly **Interactive Menu** for manual use and a **Command Line Interface (CLI)** for automation and cron jobs. + +## ๐Ÿš€ Features + +* **Hybrid Modes:** Use the interactive menu (`-i`) or command-line flags. +* **Multiple Formats:** Support for `.tar.gz` (Standard), `.tar.bz2` (High Compression), and `.zip` (Windows compatible). +* **Path Flexibility:** Choose between keeping the directory structure or a "Flat" backup (contents only). +* **Smart Restore:** Auto-detects the archive format during restorationโ€”no need to specify the file type manually. +* **Safe:** Checks for required dependencies (`zip`, `unzip`) before attempting operations. + +## ๐Ÿ“‹ Prerequisites + +The script uses standard Linux tools. For `.zip` support, ensure you have `zip` and `unzip` installed: + +\`\`\`bash +# Ubuntu/Debian +sudo apt install zip unzip + +# RHEL/CentOS +sudo yum install zip unzip +\`\`\` + +## โš™๏ธ Installation + +1. Download or create the script file: + \`\`\`bash + nano smart_backup.sh + \`\`\` +2. Paste the script code and save. +3. Make the script executable: + \`\`\`bash + chmod +x smart_backup.sh + \`\`\` + +## ๐Ÿ“– Usage + +Running the script without arguments displays the help menu: + +\`\`\`bash +./smart_backup.sh +\`\`\` + +### 1. Interactive Mode +Best for manual, ad-hoc backups. This launches a text-based menu wizard. + +\`\`\`bash +./smart_backup.sh -i +\`\`\` + +### 2. Backup via CLI +Best for scripts and automation. + +**Syntax:** +\`\`\`bash +./smart_backup.sh -b -s -d [OPTIONS] +\`\`\` + +**Examples:** + +* **Standard Backup (keeps folder name):** + \`\`\`bash + ./smart_backup.sh -b -s /var/www/html -d /backups + \`\`\` +* **Backup with specific format (bzip2):** + \`\`\`bash + ./smart_backup.sh -b -s /home/user/docs -d /backups -t bz2 + \`\`\` +* **"Flat" Backup (contents only, useful for dumping files directly):** + \`\`\`bash + ./smart_backup.sh -b -s /var/log -d /tmp/logs -flat + \`\`\` + +### 3. Restore via CLI + +**Syntax:** +\`\`\`bash +./smart_backup.sh -r -f -d +\`\`\` + +**Example:** +\`\`\`bash +./smart_backup.sh -r -f /backups/html_20231010.tar.gz -d /var/www +\`\`\` + +--- + +## ๐Ÿšฉ Argument Reference + +| Flag | Argument | Description | +| :--- | :--- | :--- | +| **-i** | None | Enter **Interactive Mode**. | +| **-b** | None | Trigger **Backup Mode**. Requires \`-s\` and \`-d\`. | +| **-r** | None | Trigger **Restore Mode**. Requires \`-f\`. | +| **-s** | \`\` | **Source** directory to backup. | +| **-d** | \`\` | **Destination** directory (for saving backup or unpacking restore). | +| **-f** | \`\` | **File** path of the archive to restore. | +| **-t** | \`\` | Compression type: \`gz\` (default), \`bz2\`, or \`zip\`. | +| **-flat**| None | **Flat Mode**: Backs up files inside the folder, not the folder itself. | +| **-h** | None | Show help/usage message. | + +## ๐Ÿค– Automation (Cron Job Example) + +To run a backup every day at 3:00 AM using this script: + +1. Open crontab: \`crontab -e\` +2. Add the following line: + +\`\`\`cron +0 3 * * * /path/to/smart_backup.sh -b -s /home/user/data -d /mnt/backups -t gz +\`\`\` +EOF diff --git a/SysInfoProject/BACKUP_Things/smart_backup.sh b/SysInfoProject/BACKUP_Things/smart_backup.sh new file mode 100644 index 0000000..9b5b184 --- /dev/null +++ b/SysInfoProject/BACKUP_Things/smart_backup.sh @@ -0,0 +1,262 @@ +#!/bin/bash + +# ========================================== +# Script Name: smart_backup.sh +# Description: Backup/Restore tool. Supports Interactive (-i) and CLI modes. +# ========================================== + +# Colors +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# --- 1. Usage / Help Function --- +usage() { + echo -e "${BLUE}Usage: $0 [MODE] [OPTIONS]${NC}" + echo "" + echo -e "${YELLOW}MODES:${NC}" + echo " (No arguments) Show this help message" + echo " -i Enter Interactive Menu Mode" + echo " -b Run Backup (requires -s, -d)" + echo " -r Run Restore (requires -f)" + echo "" + echo -e "${YELLOW}BACKUP OPTIONS:${NC}" + echo " -s Source directory to backup" + echo " -d Destination directory for the archive" + echo " -t Format: 'gz' (default), 'bz2', or 'zip'" + echo " -flat Save files directly (flat) instead of keeping directory structure" + echo "" + echo -e "${YELLOW}RESTORE OPTIONS:${NC}" + echo " -f Full path to the backup file to restore" + echo " -d Destination to unpack (default: current dir)" + echo "" + echo -e "${YELLOW}EXAMPLES:${NC}" + echo " Interactive: $0 -i" + echo " Backup (std): $0 -b -s /var/www -d /backups -t gz" + echo " Backup (flat): $0 -b -s /var/logs -d . -flat" + echo " Restore: $0 -r -f /backups/site.tar.gz -d /var/www" + exit 1 +} + +check_dependency() { + if ! command -v "$1" &> /dev/null; then + echo -e "${RED}Error: '$1' is not installed.${NC}" + exit 1 + fi +} + +# --- 2. Core Logic Functions --- + +core_backup() { + local SRC=$1 + local DEST=$2 + local FMT=$3 + local FLAT=$4 + + # Validations + SRC=${SRC%/} + DEST=${DEST%/} + + if [ -z "$SRC" ] || [ -z "$DEST" ]; then + echo -e "${RED}Error: Source (-s) and Destination (-d) are required.${NC}" + exit 1 + fi + if [ ! -d "$SRC" ]; then + echo -e "${RED}Error: Source directory '$SRC' does not exist.${NC}" + exit 1 + fi + mkdir -p "$DEST" + + # Filename Setup + TIMESTAMP=$(date +"%Y%m%d_%H%M%S") + BASE_NAME=$(basename "$SRC") + BACKUP_NAME="${BASE_NAME}_${TIMESTAMP}" + + # Path Strategy + if [ "$FLAT" == "true" ]; then + # Go inside, grab contents (spills out when unpacked) + cd "$SRC" || exit + TARGET="." + else + # Go to parent, grab folder name (creates folder when unpacked) + PARENT_DIR=$(dirname "$SRC") + TARGET=$(basename "$SRC") + cd "$PARENT_DIR" || exit + fi + + echo -e "${BLUE}Backing up '$SRC' to '$DEST'...${NC}" + + case $FMT in + gz|tar.gz) + tar -czf "${DEST}/${BACKUP_NAME}.tar.gz" $TARGET + FINAL_FILE="${DEST}/${BACKUP_NAME}.tar.gz" + ;; + bz2|tar.bz2) + tar -cjf "${DEST}/${BACKUP_NAME}.tar.bz2" $TARGET + FINAL_FILE="${DEST}/${BACKUP_NAME}.tar.bz2" + ;; + zip) + check_dependency "zip" + zip -r "${DEST}/${BACKUP_NAME}.zip" $TARGET + FINAL_FILE="${DEST}/${BACKUP_NAME}.zip" + ;; + *) + # Default to GZ if unknown + tar -czf "${DEST}/${BACKUP_NAME}.tar.gz" $TARGET + FINAL_FILE="${DEST}/${BACKUP_NAME}.tar.gz" + ;; + esac + + if [ $? -eq 0 ]; then + echo -e "${GREEN}Success: $FINAL_FILE${NC}" + else + echo -e "${RED}Backup Failed.${NC}" + fi +} + +core_restore() { + local FILE=$1 + local DEST=$2 + + if [ -z "$FILE" ]; then + echo -e "${RED}Error: Backup file (-f) is required.${NC}" + exit 1 + fi + if [ ! -f "$FILE" ]; then + echo -e "${RED}Error: File '$FILE' not found.${NC}" + exit 1 + fi + + # Default dest to current dir if empty + DEST=${DEST:-.} + mkdir -p "$DEST" + + echo -e "${BLUE}Restoring '$FILE' to '$DEST'...${NC}" + + if [[ "$FILE" == *.tar.gz || "$FILE" == *.tgz ]]; then + tar -xzf "$FILE" -C "$DEST" + elif [[ "$FILE" == *.tar.bz2 ]]; then + tar -xjf "$FILE" -C "$DEST" + elif [[ "$FILE" == *.zip ]]; then + check_dependency "unzip" + unzip "$FILE" -d "$DEST" + else + echo -e "${RED}Unknown format. Cannot extract.${NC}" + exit 1 + fi + + echo -e "${GREEN}Restore Complete.${NC}" +} + +# --- 3. Interactive Wrapper --- +run_interactive() { + while true; do + clear + echo -e "${BLUE}=== INTERACTIVE BACKUP TOOL ===${NC}" + echo "1) Create Backup" + echo "2) Restore Backup" + echo "3) Exit" + read -p "Choice: " OPT + + case $OPT in + 1) + read -p "Source Folder: " I_SRC + read -p "Dest Folder: " I_DEST + echo "Format: 1) gz 2) bz2 3) zip" + read -p "Select [1-3]: " F_OPT + case $F_OPT in + 1) I_FMT="gz" ;; + 2) I_FMT="bz2" ;; + 3) I_FMT="zip" ;; + *) I_FMT="gz" ;; + esac + + echo "Structure: 1) Keep Folder Name 2) Flat (Content Only)" + read -p "Select [1-2]: " S_OPT + if [ "$S_OPT" == "2" ]; then I_FLAT="true"; else I_FLAT="false"; fi + + core_backup "$I_SRC" "$I_DEST" "$I_FMT" "$I_FLAT" + ;; + 2) + read -p "Backup File Path: " I_FILE + read -p "Restore To (Enter for current): " I_DEST + core_restore "$I_FILE" "$I_DEST" + ;; + 3) exit 0 ;; + *) echo "Invalid" ;; + esac + echo "Press Enter..." + read + done +} + +# --- 4. Main Execution & Argument Parsing --- + +# If no arguments provided, show Usage +if [ $# -eq 0 ]; then + usage +fi + +MODE="" +SRC="" +DEST="" +FILE="" +FMT="gz" +FLAT="false" + +# Parse Arguments +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + -i|--interactive) + run_interactive + exit 0 + ;; + -b|--backup) + MODE="backup" + shift + ;; + -r|--restore) + MODE="restore" + shift + ;; + -s|--source) + SRC="$2" + shift; shift + ;; + -d|--dest) + DEST="$2" + shift; shift + ;; + -f|--file) + FILE="$2" + shift; shift + ;; + -t|--type) + FMT="$2" + shift; shift + ;; + -flat) + FLAT="true" + shift + ;; + -h|--help) + usage + ;; + *) + echo -e "${RED}Unknown option: $1${NC}" + usage + ;; + esac +done + +# Execute based on mode +if [ "$MODE" == "backup" ]; then + core_backup "$SRC" "$DEST" "$FMT" "$FLAT" +elif [ "$MODE" == "restore" ]; then + core_restore "$FILE" "$DEST" +else + usage +fi diff --git a/SysInfoProject/Linux/Find_User_INFO/change_uid/README.md b/SysInfoProject/Linux/Find_User_INFO/change_uid/README.md new file mode 100644 index 0000000..fddca19 --- /dev/null +++ b/SysInfoProject/Linux/Find_User_INFO/change_uid/README.md @@ -0,0 +1,78 @@ +# change_uid.sh - Safe Linux UID Modification Script + +A robust, interactive bash script designed to safely change a user's User ID (UID) in Linux. + +Changing a UID manually can leave behind orphaned files and cause system conflicts if the user has running processes. This script automates the safety checks, handles active processes, permanently changes the UID, and performs a surgical filesystem scan to update file ownership exactly where you need it. + +## โœจ Features + +* **Targeted Scanning (`--scan-path`):** Save time by restricting the file ownership update to a specific directory (e.g., `/home` or `/var/www`). Defaults to scanning the entire root (`/`) if omitted. +* **Dry-Run Mode (`--dry-run`):** Safely simulate the entire process. See which processes would be killed and exactly which files would be modified without making any actual changes to your system. +* **Custom Log Paths (`--log-dir`):** Save your audit logs to a centralized directory of your choosing (defaults to `/var/log` or `/tmp` for dry-runs). +* **Process Management:** Detects if the target user is currently running any processes and provides an interactive prompt to safely terminate them before modifying the account. +* **Collision Detection:** Verifies that your chosen new UID is not already taken by another user or system account. +* **Detailed Auditing:** Generates a line-by-line log of every file modified, including the target scan path and timestamps. + +## ๐Ÿ“‹ Prerequisites + +* **OS:** Linux +* **Privileges:** Root access (`sudo`) is required to modify users and change system-wide file ownership. +* **Dependencies:** Standard coreutils (`usermod`, `find`, `chown`, `pgrep`, `pkill`) + +## ๐Ÿš€ Installation + +Clone the repository and make the script executable: + +```bash +# Clone the repository +git clone [https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.git](https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.git) + +# Navigate into the directory +cd YOUR_REPOSITORY + +# Make the script executable +chmod +x change_uid.sh +``` +(Note: Replace YOUR_USERNAME and YOUR_REPOSITORY with your actual GitHub details). + +## ๐Ÿ’ป Usage +The script is interactive. Execute it with sudo and follow the on-screen prompts to enter the username and the new UID. You can append optional flags to customize its behavior. + +Basic Execution (Scans entire filesystem) +```bash +sudo ./change_uid.sh +``` + +### Targeted Scan (Recommended for speed) +Limit the file ownership updates to a specific folder, such as the user's web directory. + +```bash +sudo ./change_uid.sh --scan-path /var/www/html +``` +### Dry-Run (Simulation) +Highly recommended before making permanent changes. Simulates the update on a specific directory and outputs the simulated log to a custom folder. + +```bash +sudo ./change_uid.sh --dry-run --scan-path /home --log-dir /tmp/uid_tests +``` +### Custom Log Directory +Direct the output logs to a specific folder. If the directory does not exist, the script will attempt to create it automatically. + +```bash +sudo ./change_uid.sh --scan-path /opt/data --log-dir /opt/admin/logs +``` +### Help Menu +```bash +sudo ./change_uid.sh --help +``` +## โš ๏ธ Important Safety Notes +Time Consumption: If you do not provide a --scan-path, the script runs a full filesystem scan (find /). This can take several minutes on systems with large hard drives or network-attached storage. + +Virtual Filesystems: The script intelligently ignores /proc, /sys, and /dev to prevent permission errors and speed up scans. + +Symlinks: The script uses chown -h to change the ownership of symbolic links themselves, rather than following the link and accidentally changing the target file's owner. + +Backups: Always ensure you have a backup of critical system configurations before modifying user accounts. + +## ๐Ÿ“„ License +This project is licensed under the MIT License. You are free to use, modify, and distribute this script as needed. diff --git a/SysInfoProject/Linux/Find_User_INFO/change_uid/change_uid.sh b/SysInfoProject/Linux/Find_User_INFO/change_uid/change_uid.sh new file mode 100644 index 0000000..73c564e --- /dev/null +++ b/SysInfoProject/Linux/Find_User_INFO/change_uid/change_uid.sh @@ -0,0 +1,194 @@ +#!/bin/bash + +# --- 1. Usage Function --- +usage() { + echo "Usage: $0 [OPTIONS]" + echo "Change a user's UID safely, updating file ownership across the system." + echo "" + echo "Options:" + echo " -h, --help Display this help message and exit." + echo " --dry-run Simulate the process without making actual changes." + echo " --log-dir Specify a custom directory to save the log file." + echo " --scan-path Specify which directory to scan for old files (Default: /)" + echo "" + echo "Examples:" + echo " sudo $0" + echo " sudo $0 --dry-run --scan-path /home" + echo " sudo $0 --scan-path /var/www --log-dir /opt/admin/logs" +} + +# --- 2. Argument Parsing --- +DRY_RUN=false +LOG_DIR="" +SCAN_PATH="/" + +while [[ "$#" -gt 0 ]]; do + case $1 in + -h|--help) + usage + exit 0 + ;; + --dry-run) + DRY_RUN=true + shift + ;; + --log-dir) + if [[ -n "$2" && "$2" != -* ]]; then + LOG_DIR="$2" + shift 2 + else + echo "Error: Argument for $1 is missing." >&2 + usage + exit 1 + fi + ;; + --scan-path) + if [[ -n "$2" && "$2" != -* ]]; then + SCAN_PATH="$2" + shift 2 + else + echo "Error: Argument for $1 is missing." >&2 + usage + exit 1 + fi + ;; + *) + echo "Error: Unknown parameter passed: $1" >&2 + usage + exit 1 + ;; + esac +done + +if [ "$DRY_RUN" = true ]; then + echo "=========================================" + echo " RUNNING IN DRY-RUN MODE (SIMULATION) " + echo "=========================================" +fi + +# Validate scan path +if [[ ! -d "$SCAN_PATH" ]]; then + echo "Error: The scan path '$SCAN_PATH' does not exist or is not a directory." >&2 + exit 1 +fi + +# --- 3. Root Check --- +if [[ "${EUID}" -ne 0 ]]; then + echo "Error: This script must be run as root. Try using sudo." >&2 + exit 1 +fi + +# --- 4. Gather Input --- +read -p "Enter the username: " username + +if ! id "$username" &>/dev/null; then + echo "Error: User '$username' does not exist." >&2 + exit 1 +fi + +current_uid=$(id -u "$username") +echo "Current UID for $username is: $current_uid" + +read -p "Enter the new UID: " new_uid + +if ! [[ "$new_uid" =~ ^[0-9]+$ ]]; then + echo "Error: The new UID must be a positive integer." >&2 + exit 1 +fi + +if getent passwd "$new_uid" >/dev/null 2>&1; then + existing_user=$(getent passwd "$new_uid" | cut -d: -f1) + echo "Error: UID $new_uid is already in use by user '$existing_user'." >&2 + exit 1 +fi + +# --- 5. Process Check --- +if pgrep -u "$username" >/dev/null; then + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would prompt to terminate running processes for '$username'." + else + echo "Warning: User '$username' has running processes. usermod will fail if processes are running." + read -p "Do you want to terminate these processes now? (y/N): " kill_procs + if [[ "$kill_procs" =~ ^[Yy]$ ]]; then + pkill -u "$username" + echo "Processes terminated." + sleep 2 + else + echo "Aborting UID change. Please stop the user's processes manually and try again." + exit 1 + fi + fi +fi + +# --- 6. Execute UID Change --- +if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would run: usermod -u $new_uid $username" +else + echo "Changing UID for $username from $current_uid to $new_uid..." + if usermod -u "$new_uid" "$username"; then + echo "Success! UID for $username is now $(id -u "$username")." + else + echo "Error: Failed to change UID." >&2 + exit 1 + fi +fi + +# --- 7. Setup Logging Directory --- +timestamp=$(date +"%Y%m%d_%H%M%S") + +if [[ -z "$LOG_DIR" ]]; then + if [ "$DRY_RUN" = true ]; then + LOG_DIR="/tmp" + else + LOG_DIR="/var/log" + fi +fi + +if [[ ! -d "$LOG_DIR" ]]; then + echo "Log directory '$LOG_DIR' does not exist. Attempting to create it..." + mkdir -p "$LOG_DIR" 2>/dev/null || { echo "Error: Failed to create log directory '$LOG_DIR'. Check permissions." >&2; exit 1; } +fi + +if [ "$DRY_RUN" = true ]; then + log_file="${LOG_DIR}/uid_change_${username}_${timestamp}_DRYRUN.log" +else + log_file="${LOG_DIR}/uid_change_${username}_${timestamp}.log" +fi + +# --- 8. Filesystem Update & Logging --- +if [ "$DRY_RUN" = true ]; then + echo "--------------------------------------------------------" + echo "Scanning '$SCAN_PATH' to find files owned by UID $current_uid..." + echo "Simulated log will be written to: $log_file" +else + echo "--------------------------------------------------------" + echo "Scanning '$SCAN_PATH' for leftover files owned by UID $current_uid..." + echo "Logging changes to: $log_file" +fi + +echo "=== UID Change Log for $username (Dry-Run: $DRY_RUN) ===" > "$log_file" +echo "Old UID: $current_uid -> New UID: $new_uid" >> "$log_file" +echo "Target Scan Path: $SCAN_PATH" >> "$log_file" +echo "Date: $(date)" >> "$log_file" +echo "-----------------------------------" >> "$log_file" + +find "$SCAN_PATH" \( -path /proc -o -path /sys -o -path /dev \) -prune -o -user "$current_uid" -print0 2>/dev/null | while IFS= read -r -d $'\0' file; do + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would change ownership: $file" >> "$log_file" + else + chown -h "$new_uid" "$file" + echo "[$(date +'%H:%M:%S')] Changed: $file" >> "$log_file" + fi +done + +lines=$(wc -l < "$log_file") +files_found=$((lines - 5)) # Adjusted for the new header line + +echo "--------------------------------------------------------" +if [ "$DRY_RUN" = true ]; then + echo "Done Simulation! Found $files_found files that would need ownership updates in '$SCAN_PATH'." + echo "Review the simulated target list at: $log_file" +else + echo "Done! Updated ownership on $files_found files inside '$SCAN_PATH'." + echo "You can review the full list of changed files at: $log_file" +fi diff --git a/SysInfoProject/My_SSH/README.md b/SysInfoProject/My_SSH/README.md new file mode 100644 index 0000000..39b2c20 --- /dev/null +++ b/SysInfoProject/My_SSH/README.md @@ -0,0 +1,57 @@ +cat << 'EOF' > README.md +# SSH Key Setup Script for User `mgveliz` + +## ๐Ÿ“‹ Overview +This repository contains a Bash script (`setup_ssh_mgveliz.sh`) designed to automate the provisioning of SSH access for the user **mgveliz**. + +It ensures that the SSH directory structure exists, applies the correct security permissions (chmod 700/600), and safely appends the specific public key to the `authorized_keys` file without creating duplicates. + +## ๐Ÿš€ Features +* **Safety Checks:** Verifies the target user exists before running. +* **Idempotency:** Checks if the specific public key already exists to avoid duplicate entries. +* **Security Compliance:** Enforces strict permissions: + * `~/.ssh` directory: **700** (`drwx------`) + * `authorized_keys` file: **600** (`-rw-------`) +* **Ownership Fix:** Ensures all files are owned by `mgveliz:mgveliz` regardless of who runs the script (sudo). + +## ๐Ÿ› ๏ธ Prerequisites +* **OS:** Linux (Debian, Ubuntu, RHEL, SUSE, etc.) +* **Privileges:** Must be run with `sudo` or as root. +* **User:** The target user `mgveliz` must already exist on the system. + +## ๐Ÿ’ป Usage + +1. **Download or Clone the script** to the server. + +2. **Make the script executable:** + ```bash + chmod +x setup_ssh_mgveliz.sh + ``` + +3. **Run the script with sudo:** + ```bash + sudo ./setup_ssh_mgveliz.sh + ``` + +## ๐Ÿ” Script Logic Breakdown + +| Step | Action | Details | +| :--- | :--- | :--- | +| 1 | **Check User** | Verifies `id mgveliz` returns a valid user. Exits if not found. | +| 2 | **Create Dir** | Creates `/home/mgveliz/.ssh` if missing (`mkdir -vp`). | +| 3 | **Perms (Dir)** | Sets `.ssh` folder to `700`. | +| 4 | **Append Key** | Greps the `authorized_keys` file for the specific key string. Appends only if missing. | +| 5 | **Perms (File)** | Sets `authorized_keys` file to `600`. | +| 6 | **Ownership** | Runs `chown -R mgveliz:mgveliz` on the `.ssh` folder to ensure the user owns their own keys. | + +## ๐Ÿ”‘ Key Details +The script installs the following RSA key (associated with `mgveliz@oxya.com`): + +> `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLSV3...` + +## โš™๏ธ Customization +To use this script for a different user, modify the variables at the top of `setup_ssh_mgveliz.sh`: + +```bash +TARGET_USER="new_username" +KEY_CONTENT="ssh-rsa AAAA..." diff --git a/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh b/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh new file mode 100644 index 0000000..1167965 --- /dev/null +++ b/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# 1. Define Variables +TARGET_USER="mgveliz" +TARGET_GROUP="users" +HOME_DIR="/home/$TARGET_USER" +SSH_DIR="$HOME_DIR/.ssh" +AUTH_FILE="$SSH_DIR/authorized_keys" + +# The OpenSSH Public Key provided +KEY_CONTENT="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLSV3CuCfX91OYNH+9+rzHrAiU/dr3qiHWHDqo9+ZebjJl0JoSVokzTWLZ3Loxkf2unnQTXW5+Pt4dnDoWe7zmrb5yWF1J/N0DLwCFfZFrz0jn7fLLZ+zd7ZoNA+/A+FsDpWR2Bvtf9lGKflQF2kyAJURZ/8gM3JYIiECcy02lwSdUtRXhvfyK56ac5yIhgxKVJsgF5BbFygf0r5L7Pn7W1OyUGaL9un1dONHC0++JKkHSCBBE3P+uQgUePPNtnkTtADyDIZeYCeBFRMSSta/qhp30/kIRoP5hkCwC8lFrauUEMLaLT9N0P7U4cc6qF/odkJecl9smiU9cyxwAPTpv mgveliz@oxya.com" + +# 2. Check if the user exists +if ! id "$TARGET_USER" &>/dev/null; then + echo "Error: User $TARGET_USER does not exist on this system." + exit 1 +fi + +echo "Configuring SSH access for user: $TARGET_USER" + +# 3. Create the .ssh directory if it doesn't exist +if [ ! -d "$SSH_DIR" ]; then + mkdir -vp "$SSH_DIR" + echo "Created directory: $SSH_DIR" +else + echo "Directory already exists: $SSH_DIR" +fi + +# 4. Set Directory Permissions (Strictly 700) +# 700 = rwx------ (User can read/write/execute, others cannot enter) +chmod 700 "$SSH_DIR" + +# 5. Append the key to authorized_keys +# We use grep -F (fixed string) to check if this specific key is already there +if grep -Fq "$KEY_CONTENT" "$AUTH_FILE" 2>/dev/null; then + echo "Notice: This specific key is already present in authorized_keys." +else + echo "$KEY_CONTENT" >> "$AUTH_FILE" + echo "Success: Key appended to authorized_keys." +fi + +# 6. Set File Permissions (Strictly 600) +# 600 = rw------- (User can read/write, others have no access) +chmod 600 "$AUTH_FILE" + +# 7. Fix Ownership +# Because we run this with sudo, we must ensure mgveliz owns the files, not root. +chown -R "$TARGET_USER:$TARGET_GROUP" "$SSH_DIR" + +echo "---------------------------------------------------" +echo "Setup complete. Permissions and ownership verified." diff --git a/SysInfoProject/NFS/NFS_Client/README.md b/SysInfoProject/NFS/NFS_Client/README.md new file mode 100644 index 0000000..18cae8c --- /dev/null +++ b/SysInfoProject/NFS/NFS_Client/README.md @@ -0,0 +1,35 @@ +# NFS Client Setup Script + +This script automates the process of mounting an NFS (Network File System) share from a remote server to a local directory on a Linux client. + +## ๐Ÿ“ฆ Features +- Accepts server IP, mount directory, and remote share path as arguments +- Validates if the mount point exists and prompts the user +- Mounts the NFS share from the server +- Displays a summary of the mount +- Optionally adds the mount to `/etc/fstab` for persistence + +## โš™๏ธ Requirements +- Linux system with NFS client utilities installed (`nfs-utils` or `nfs-common`) +- Root or sudo privileges + +## ๐Ÿš€ Usage +```bash +sudo ./nfs_client_setup.sh +``` + +### Example +```bash +sudo ./nfs_client_setup.sh 192.168.1.10 /mnt/nfs/shared /srv/nfs/shared +``` + +## ๐Ÿ“ Output +- Creates the mount point if it doesn't exist +- Mounts the NFS share from the specified remote directory +- Displays the current mount status + +## ๐Ÿ“Œ fstab Option +After mounting, the script will ask if you want to make the mount permanent by adding an entry to `/etc/fstab`. This ensures the NFS share is mounted automatically on system boot. + +## ๐Ÿ“„ License +This script is provided as-is without warranty. Use at your own risk. diff --git a/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh b/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh new file mode 100644 index 0000000..1488b04 --- /dev/null +++ b/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# NFS Client Setup Script with REMOTE_DIR Argument + +# Usage check +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + exit 1 +fi + +SERVER_IP="$1" +MOUNT_DIR="$2" +REMOTE_DIR="$3" + +# Check if mount point exists +if [ -d "$MOUNT_DIR" ]; then + echo "โš ๏ธ Mount point $MOUNT_DIR already exists." + read -p "Do you want to continue using this mount point? (y/n): " CONFIRM + if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then + echo "โŒ Operation cancelled by user." + exit 1 + fi +else + echo " Creating mount point $MOUNT_DIR..." + if ! mkdir -p "$MOUNT_DIR"; then + echo "โŒ Failed to create mount point." + exit 1 + fi +fi + +# Mount the NFS share +echo " Mounting $SERVER_IP:$REMOTE_DIR to $MOUNT_DIR..." +if mount | grep -q "$MOUNT_DIR"; then + echo "โœ… Already mounted." +else + if ! mount "$SERVER_IP:$REMOTE_DIR" "$MOUNT_DIR"; then + echo "โŒ Mount failed. Please check server availability and permissions." + exit 1 + fi + echo "โœ… Mount successful." +fi + +# Summary +echo -e " +๐Ÿ“ฆ NFS Client Mount Summary:" +echo "Server IP : $SERVER_IP" +echo "Remote Share : $REMOTE_DIR" +echo "Mount Point : $MOUNT_DIR" +mount | grep "$MOUNT_DIR" + +# Ask to add to /etc/fstab +read -p "Do you want to make this mount permanent in /etc/fstab? (y/n): " ADD_FSTAB +if [[ "$ADD_FSTAB" == "y" || "$ADD_FSTAB" == "Y" ]]; then + echo "$SERVER_IP:$REMOTE_DIR $MOUNT_DIR nfs defaults 0 0" >> /etc/fstab + echo "โœ… Entry added to /etc/fstab." +fi diff --git a/SysInfoProject/NFS/README.md b/SysInfoProject/NFS/README.md new file mode 100644 index 0000000..919c4f0 --- /dev/null +++ b/SysInfoProject/NFS/README.md @@ -0,0 +1,38 @@ +# NFS Export Setup Script + +This script automates the setup of an NFS (Network File System) export on a Linux server. It includes safety checks, backup of the `/etc/exports` file, and rollback support in case of failure. + +## ๐Ÿ“ฆ Features +- Accepts shared directory and client IP as arguments +- Validates if the directory exists and prompts the user +- Backs up `/etc/exports` before making changes +- Adds export rule if not already present +- Applies export configuration +- Supports rollback if export fails +- Displays a summary of the export configuration + +## ๐Ÿ› ๏ธ Requirements +- Linux system with NFS utilities installed (`nfs-utils`) +- Root or sudo privileges + +## ๐Ÿš€ Usage +```bash +sudo ./nfs_export_setup.sh +``` + +### Example +```bash +sudo ./nfs_export_setup.sh /srv/nfs/shared 192.168.1.100 +``` + +## ๐Ÿ“ Output +- Creates the shared directory if it doesn't exist +- Adds an export rule to `/etc/exports` +- Backs up the original exports file to `/etc/exports.bak_` +- Displays the current export list using `exportfs -v` + +## ๐Ÿ”„ Rollback +If the export configuration fails, the script prompts the user to restore the previous version of `/etc/exports` from the backup. + +## ๐Ÿ“„ License +This script is provided as-is without warranty. Use at your own risk. diff --git a/SysInfoProject/NFS/nfs_export_setup.sh b/SysInfoProject/NFS/nfs_export_setup.sh new file mode 100644 index 0000000..920fde5 --- /dev/null +++ b/SysInfoProject/NFS/nfs_export_setup.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# NFS Server Setup Script with Backup and Rollback + +# Usage check +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +SHARE_DIR="$1" +CLIENT_IP="$2" +EXPORTS_FILE="/etc/exports" +BACKUP_FILE="/etc/exports.bak_$(date +%Y%m%d_%H%M%S)" + +# Check if the directory exists +if [ -d "$SHARE_DIR" ]; then + echo "โš ๏ธ Directory $SHARE_DIR already exists." + read -p "Do you want to continue using this directory? (y/n): " CONFIRM + if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then + echo "โŒ Operation cancelled by user." + exit 1 + fi +else + echo "๐Ÿ“ Creating directory $SHARE_DIR..." + if ! mkdir -p "$SHARE_DIR"; then + echo "โŒ Failed to create directory $SHARE_DIR." + exit 1 + fi + chown nobody:nogroup "$SHARE_DIR" +fi + +# Backup /etc/exports +echo "๐Ÿ—‚๏ธ Backing up $EXPORTS_FILE to $BACKUP_FILE..." +if ! cp "$EXPORTS_FILE" "$BACKUP_FILE"; then + echo "โŒ Failed to back up $EXPORTS_FILE." + exit 1 +fi + +# Check if the export rule already exists +if grep -q "$SHARE_DIR $CLIENT_IP" "$EXPORTS_FILE"; then + echo "๐Ÿ” Export rule for $CLIENT_IP already exists in $EXPORTS_FILE." +else + echo "โž• Adding export rule for $CLIENT_IP..." + echo "$SHARE_DIR $CLIENT_IP(rw,sync,no_subtree_check)" >> "$EXPORTS_FILE" +fi + +# Apply export configuration +echo "๐Ÿ”„ Applying export configuration..." +if ! exportfs -a; then + echo "โŒ Failed to apply export configuration." + read -p "Do you want to rollback to the previous exports file? (y/n): " ROLLBACK + if [[ "$ROLLBACK" == "y" || "$ROLLBACK" == "Y" ]]; then + echo "โช Restoring backup..." + if cp "$BACKUP_FILE" "$EXPORTS_FILE"; then + exportfs -a + echo "โœ… Rollback successful." + else + echo "โŒ Rollback failed. Manual intervention required." + fi + else + echo "โš ๏ธ Changes not rolled back. Please check manually." + fi + exit 1 +fi + +# Summary +echo -e " +๐Ÿ“ฆ NFS Export Summary:" +echo "Shared Directory : $SHARE_DIR" +echo "Client IP : $CLIENT_IP" +echo "Export Options : rw, sync, no_subtree_check" +echo "Backup File : $BACKUP_FILE" +echo "Export List:" +exportfs -v diff --git a/SysInfoProject/NetworkStuffs/Linux/README.md b/SysInfoProject/NetworkStuffs/Linux/README.md new file mode 100644 index 0000000..53d8675 --- /dev/null +++ b/SysInfoProject/NetworkStuffs/Linux/README.md @@ -0,0 +1,184 @@ +# Static IPv4 Configuration Script for NetworkManager (`nmcli`) + +This repository contains a hardened Bash script that automates the process of configuring a static IPv4 address on Linux systems using **NetworkManager** (`nmcli`). +It includes full error handling, rollback capabilities, validation logic, and optional dry-run mode for safe change previews. + +--- + +## ๐Ÿ“Œ Features + +- Configure IPv4 static addressing with: + - IP address + prefix + - Gateway + - DNS servers (optional) +- Automatic detection of active `nmcli` connection profile +- Comprehensive error handling and exit codes +- Automatic **backup** of existing connection profile +- Rollback on failure (restores original `.nmconnection`) +- Timeout support for slow networking services +- Dry-run mode for change validation +- Safe logging with clear `[INFO]`, `[WARN]`, and `[ERROR]` blocks +- IPv4 format validation for correctness and safety + +--- + +## ๐Ÿ“‚ Script File + +The script shipped with this repository: + +``` +set-static-ip-nmcli.sh +``` + +Make it executable: + +```bash +chmod +x set-static-ip-nmcli.sh +``` + +Run as root (required by NetworkManager): + +```bash +sudo ./set-static-ip-nmcli.sh ... +``` + +--- + +## ๐Ÿš€ Usage + +### Basic static IP configuration + +```bash +sudo ./set-static-ip-nmcli.sh -i ens192 -a 10.54.240.204 -p 25 -g 10.54.240.129 +``` + +### Add DNS servers + +```bash +sudo ./set-static-ip-nmcli.sh -i ens192 -a 10.54.240.204 -p 25 -g 10.54.240.129 -d 8.8.8.8,1.1.1.1 +``` + +### Adjust nmcli timeout + +```bash +sudo ./set-static-ip-nmcli.sh -t 30 ... +``` + +### Dry-run mode (no changes made) + +```bash +sudo ./set-static-ip-nmcli.sh --dry-run -i ens192 -a 10.54.240.204 -p 25 -g 10.54.240.129 +``` + +--- + +## ๐Ÿ“ Parameters + +| Flag | Description | Required | +|------|-------------|----------| +| `-i` | Network interface (`ens192`, `eth0`, etc.) | โœ” | +| `-a` | IPv4 address | โœ” | +| `-p` | Prefix length (`25` for `/25`) | โœ” | +| `-g` | Default IPv4 gateway | โœ” | +| `-d` | One or more DNS servers (comma-separated) | โœ˜ | +| `-t` | Timeout (seconds) for `nmcli` operations | โœ˜ | +| `--dry-run` | Do not apply โ€” only show commands | โœ˜ | +| `-h` | Show help | โœ˜ | + +--- + +## ๐Ÿ”’ Rollback and Backup + +Before modifying anything, the script exports a full backup: + +``` +backup--YYYYMMDD-HHMMSS.nmconnection +``` + +If any command fails during configuration or interface restart: + +- The script **automatically imports** the backup +- Attempts to restore the previous connection state + +You can manually restore a backup at any time: + +```bash +sudo nmcli connection import type file file backup-file.nmconnection +``` + +--- + +## ๐Ÿงช Verification + +After applying changes, the script prints: + +- IPv4 address on the interface +- Default routes +- NetworkManager connection summary + +If verification fails, the script exits with a failure code. + +--- + +## โ— Exit Codes + +| Code | Meaning | +|------|---------| +| `0` | Success | +| `1` | Not root / `nmcli` missing | +| `2` | Invalid arguments / validation failure | +| `3` | Interface or connection profile missing | +| `4` | Backup export failed | +| `5` | Failed to apply IPv4 settings | +| `6` | Failed to restart connection | +| `7` | Verification failure | +| `8` | Rollback failed; manual fix required | + +--- + +## โš ๏ธ Remote Server Warning + +Running: + +``` +nmcli connection down +``` + +**will disconnect your SSH session**. + +If using this script over SSH, consider: + +- Running inside a console (iLO, iDRAC, VMware console) +- Using `at` or `systemd-run` to schedule a rollback if the server becomes unreachable + +Ask if you want an automated rollback timer added. + +--- + +## ๐Ÿ›  Requirements + +- Linux with **NetworkManager** +- `nmcli` available in `$PATH` +- Root privileges (`sudo`) + +--- + +## ๐Ÿ“„ License + +MIT License (or specify your own โ€” let me know if you want a template added). + +--- + +## ๐Ÿค Contributing + +Pull requests and improvements are welcome! +Feel free to open issues for feature requests or bug reports. + +--- + +## ๐Ÿ‘ค Author + +**Manuel Gabriel Veliz** +Contract SAP Basis Engineer + +--- diff --git a/SysInfoProject/NetworkStuffs/Linux/set-static-ip-nmcli.sh b/SysInfoProject/NetworkStuffs/Linux/set-static-ip-nmcli.sh new file mode 100644 index 0000000..6dc263d --- /dev/null +++ b/SysInfoProject/NetworkStuffs/Linux/set-static-ip-nmcli.sh @@ -0,0 +1,254 @@ +#!/usr/bin/env bash +# +# set-static-ip-nmcli.sh +# Configure a NetworkManager connection with a static IPv4 address using nmcli, +# with robust error handling, timeouts, and rollback support. +# +# Usage: +# sudo ./set-static-ip-nmcli.sh -i ens192 -a 10.54.240.204 -p 25 -g 10.54.240.129 [-d 8.8.8.8,1.1.1.1] [--dry-run] [-t 20] +# +# Exit codes: +# 0 Success +# 1 Not root or nmcli missing +# 2 Usage / argument validation error +# 3 Interface / connection profile not found +# 4 Backup export failed +# 5 Apply settings failed +# 6 Restarting connection failed +# 7 Verification failed +# 8 Rollback failed (after a prior failure) + +set -euo pipefail + +# --- Globals --- +BACKUP="" +CONN_NAME="" +IFACE="" +ADDR="" +PREFIX="" +GATEWAY="" +DNS_LIST="" +DRY_RUN=0 +NM_TIMEOUT=15 # seconds for nmcli -w + +# --- Logging helpers --- +log() { printf '[INFO] %s\n' "$*" >&2; } +warn() { printf '[WARN] %s\n' "$*" >&2; } +err() { printf '[ERROR] %s\n' "$*" >&2; } + +# --- Trap for diagnostics --- +# Reports command and line on unhandled error (still allows our custom handling). +trap 'rc=$?; err "Unhandled error at line $LINENO. Last command failed. Exit code: $rc"; exit $rc' ERR + +# --- Show usage --- +usage() { + cat <<'EOF' +Usage: + sudo ./set-static-ip-nmcli.sh -i -a -p -g [-d ] [--dry-run] [-t ] + +Required: + -i Network interface (e.g., ens192) + -a IPv4 address (e.g., 10.54.240.204) + -p Prefix length (e.g., 25 for /25) + -g IPv4 gateway (e.g., 10.54.240.129) + +Optional: + -d Comma-separated DNS servers (e.g., 8.8.8.8,1.1.1.1) + --dry-run Show what would be done without making changes + -t Timeout (seconds) for nmcli commands (default 15) + +Examples: + sudo ./set-static-ip-nmcli.sh -i ens192 -a 10.54.240.204 -p 25 -g 10.54.240.129 + sudo ./set-static-ip-nmcli.sh -i ens192 -a 10.54.240.204 -p 25 -g 10.54.240.129 -d 8.8.8.8,1.1.1.1 -t 20 +EOF +} + +# --- Validator helpers --- +is_ipv4() { + local ip="$1" + # Basic pattern + numeric ranges + [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1 + IFS='.' read -r o1 o2 o3 o4 <<<"$ip" + for o in "$o1" "$o2" "$o3" "$o4"; do + [[ "$o" -ge 0 && "$o" -le 255 ]] || return 1 + done + return 0 +} + +is_prefix() { + local p="$1" + [[ "$p" =~ ^[0-9]+$ ]] && [[ "$p" -ge 0 && "$p" -le 32 ]] +} + +# --- Command runner (with dry-run support) --- +run() { + local desc="$1"; shift + if (( DRY_RUN )); then + log "[dry-run] $desc: $*" + return 0 + fi + log "$desc: $*" + if ! "$@"; then + err "Failed: $desc" + return 1 + fi +} + +# --- Parse arguments --- +while (( "$#" )); do + case "$1" in + -i) IFACE="${2:-}"; shift 2 ;; + -a) ADDR="${2:-}"; shift 2 ;; + -p) PREFIX="${2:-}"; shift 2 ;; + -g) GATEWAY="${2:-}"; shift 2 ;; + -d) DNS_LIST="${2:-}"; shift 2 ;; + -t) NM_TIMEOUT="${2:-}"; shift 2 ;; + --dry-run) DRY_RUN=1; shift ;; + -h|--help) usage; exit 0 ;; + *) err "Unknown argument: $1"; usage; exit 2 ;; + esac +done + +# --- Basic validation --- +if [[ -z "${IFACE}" || -z "${ADDR}" || -z "${PREFIX}" || -z "${GATEWAY}" ]]; then + err "Missing required arguments." + usage + exit 2 +fi + +if [[ $EUID -ne 0 ]]; then + err "Please run as root (use sudo)." + exit 1 +fi + +if ! command -v nmcli >/dev/null 2>&1; then + err "nmcli not found. Ensure NetworkManager is installed." + exit 1 +fi + +if ! is_ipv4 "$ADDR"; then + err "Invalid IPv4 address: $ADDR" + exit 2 +fi + +if ! is_prefix "$PREFIX"; then + err "Invalid prefix length (0-32 expected): $PREFIX" + exit 2 +fi + +if ! is_ipv4 "$GATEWAY"; then + err "Invalid IPv4 gateway: $GATEWAY" + exit 2 +fi + +# --- Ensure the interface exists in NetworkManager --- +if ! nmcli -t -f DEVICE device status | awk -F: '{print $1}' | grep -qx "$IFACE"; then + err "Interface '$IFACE' not found in NetworkManager." + nmcli device status || true + exit 3 +fi + +# --- Resolve connection name bound to the device --- +CONN_NAME="$(nmcli -t -f NAME,DEVICE connection show --active | awk -F: -v dev="$IFACE" '$2==dev {print $1; exit}')" +if [[ -z "$CONN_NAME" ]]; then + CONN_NAME="$(nmcli -t -f NAME,DEVICE connection show | awk -F: -v dev="$IFACE" '$2==dev {print $1; exit}')" +fi +if [[ -z "$CONN_NAME" ]]; then + err "Could not determine the connection profile for device '$IFACE'." + err "Tip: Create/attach a connection profile to this device first (e.g., 'nmcli con add ...')." + exit 3 +fi +log "Using connection profile: $CONN_NAME (device: $IFACE)" + +# --- Backup current profile --- +BACKUP="backup-${CONN_NAME// /_}-$(date +%Y%m%d-%H%M%S).nmconnection" +if ! run "Export backup to $BACKUP" nmcli connection export "$CONN_NAME" "$BACKUP"; then + exit 4 +fi + +# --- Apply settings --- +CIDR="${ADDR}/${PREFIX}" +if ! run "Set IPv4 method manual" nmcli -w "$NM_TIMEOUT" connection modify "$CONN_NAME" ipv4.method manual; then + warn "Attempting rollback..." + if ! nmcli connection import type file file "$BACKUP" >/dev/null 2>&1; then + err "Rollback failed. Manual intervention required." + exit 8 + fi + exit 5 +fi + +if ! run "Set IPv4 address to $CIDR" nmcli -w "$NM_TIMEOUT" connection modify "$CONN_NAME" ipv4.addresses "$CIDR"; then + warn "Attempting rollback..." + if ! nmcli connection import type file file "$BACKUP" >/dev/null 2>&1; then + err "Rollback failed. Manual intervention required." + exit 8 + fi + exit 5 +fi + +if ! run "Set IPv4 gateway to $GATEWAY" nmcli -w "$NM_TIMEOUT" connection modify "$CONN_NAME" ipv4.gateway "$GATEWAY"; then + warn "Attempting rollback..." + if ! nmcli connection import type file file "$BACKUP" >/dev/null 2>&1; then + err "Rollback failed. Manual intervention required." + exit 8 + fi + exit 5 +fi + +if [[ -n "$DNS_LIST" ]]; then + DNS_SPACED="${DNS_LIST//,/ }" + if ! run "Set DNS to $DNS_SPACED" nmcli -w "$NM_TIMEOUT" connection modify "$CONN_NAME" ipv4.dns "$DNS_SPACED"; then + warn "Attempting rollback..." + if ! nmcli connection import type file file "$BACKUP" >/dev/null 2>&1; then + err "Rollback failed. Manual intervention required." + exit 8 + fi + exit 5 + fi +fi + +# --- Restart connection (down/up) --- +# NOTE: On remote hosts, this may drop your SSH session. +if ! run "Bring connection down" nmcli -w "$NM_TIMEOUT" connection down "$CONN_NAME"; then + warn "Down failed; attempting to continue with up..." +fi + +if ! run "Bring connection up" nmcli -w "$NM_TIMEOUT" connection up "$CONN_NAME"; then + warn "Attempting rollback to previous profile..." + # Try rollback import and activate the old profile name if preserved + if ! nmcli connection import type file file "$BACKUP" >/dev/null 2>&1; then + err "Rollback failed. Manual intervention required." + exit 8 + fi + # Try to reactivate after import (best-effort) + nmcli -w "$NM_TIMEOUT" connection up "$CONN_NAME" || true + exit 6 +fi + +# --- Verification --- +VERIFIED=0 +{ + ip -4 addr show dev "$IFACE" | grep -q "$ADDR/$PREFIX" && VERIFIED=1 +} || true + +if (( VERIFIED == 0 )); then + warn "Verification: IP $CIDR not present on $IFACE after restart." + warn "Routes and nmcli summary will be printed for troubleshooting." +fi + +log "IPv4 addresses on $IFACE:" +ip -4 addr show dev "$IFACE" | sed 's/^/ /' || true + +log "Default IPv4 routes:" +ip -4 route show default | sed 's/^/ /' || true + +log "nmcli connection summary:" +nmcli -f NAME,DEVICE,IP4.METHOD,IP4.ADDRESS,IP4.GATEWAY,IP4.DNS connection show "$CONN_NAME" | sed 's/^/ /' || true + +if (( VERIFIED == 0 )); then + err "Verification failed: expected $CIDR on $IFACE." + exit 7 +fi + +log "Success. Backup saved at: $BACKUP" +exit 0 diff --git a/SysInfoProject/README.md b/SysInfoProject/README.md new file mode 100644 index 0000000..1a61400 --- /dev/null +++ b/SysInfoProject/README.md @@ -0,0 +1,51 @@ + +# SysInfo Bash Script + +This is a modular, menu-driven Bash script designed to provide system information and perform basic administrative tasks on a Linux server or desktop. + +## ๐Ÿ“ Modules + +- **main.sh**: Core logic and execution flow. +- **functions.sh**: Utility functions for formatting and display. +- **menu.sh**: Menu rendering and user input handling. + +## ๐Ÿš€ Features + +- View OS, hostname, DNS, and network info +- Monitor memory, disk, and process usage +- Manage users and groups +- Perform file operations (create, delete, compress, etc.) +- Create symbolic links with validation +- Logging and root access checks + +## ๐Ÿ› ๏ธ Requirements + +- Bash shell +- Root privileges (required for user and system operations) + +## ๐Ÿ“ฆ Usage + +1. Make sure all scripts are executable: + ```bash + chmod +x main.sh functions.sh menu.sh + ``` + +2. Run the main script: + ```bash + sudo ./main.sh + ``` + +3. Follow the on-screen menu to perform operations. + +## ๐Ÿ“ Logging + +All actions are logged to `/var/log/sysinop.log`. + +## ๐Ÿ”’ Security + +The script checks for root access before execution and validates inputs for critical operations. + +## ๐Ÿ“ฌ Author + +Originally created by Sathish Arthar (Jan 2014) +Enhanced and modularized for maintainability and security. diff --git a/SysInfoProject/SAP/Export-SAPTables.ps1 b/SysInfoProject/SAP/Export-SAPTables.ps1 new file mode 100644 index 0000000..473acf7 --- /dev/null +++ b/SysInfoProject/SAP/Export-SAPTables.ps1 @@ -0,0 +1,59 @@ +# --------------------------------------------------------------- +# Script: Export-SAPTables.ps1 +# Purpose: Export SAP tables using R3trans (Windows) +# Author: Manuel Gabriel Veliz (SAP Basis) +# --------------------------------------------------------------- + +# ---- CONFIG ---------------------------------------------------- + +# SAP SID +$SID = "PRD" + +# Path to R3trans binary +$R3transPath = "C:\usr\sap\$SID\SYS\exe\uc\NTAMD64\R3trans.exe" + +# Working directory for export +$WorkDir = "C:\usr\sap\trans\export" +New-Item -ItemType Directory -Force -Path $WorkDir | Out-Null + +# Control and log files +$CtlFile = "$WorkDir\export_tables.ctl" +$LogFile = "$WorkDir\export_tables.log" + +# ---- EXECUTION ------------------------------------------------ + +Write-Host "------------------------------------------------------------" +Write-Host " SAP Table Export via R3trans (PowerShell)" +Write-Host " Control File: $CtlFile" +Write-Host " Log File: $LogFile" +Write-Host " Working Dir: $WorkDir" +Write-Host "------------------------------------------------------------" + +# Check if R3trans exists +if (-Not (Test-Path $R3transPath)) { + Write-Host "ERROR: R3trans not found at $R3transPath" -ForegroundColor Red + exit 1 +} + +# Copy control file to working directory if needed +if (-Not (Test-Path $CtlFile)) { + Write-Host "ERROR: Control file not found at $CtlFile" -ForegroundColor Red + exit 1 +} + +# Run R3trans +& "$R3transPath" $CtlFile | Out-File -FilePath $LogFile -Encoding utf8 + +# ---- RESULT CHECK --------------------------------------------- + +$ExitCode = $LASTEXITCODE + +if ($ExitCode -eq 0) { + Write-Host "โœ” Export completed successfully." -ForegroundColor Green + Write-Host " Output file: $WorkDir\table_export.dat" +} else { + Write-Host "โŒ Export failed with Return Code: $ExitCode" -ForegroundColor Red + Write-Host " Check log: $LogFile" +} + +exit $ExitCode diff --git a/SysInfoProject/SAP/SAP_RSYNC/README.MD b/SysInfoProject/SAP/SAP_RSYNC/README.MD new file mode 100644 index 0000000..2ab9691 --- /dev/null +++ b/SysInfoProject/SAP/SAP_RSYNC/README.MD @@ -0,0 +1,83 @@ +```python +readme_content = """# SAP Environment Sync Script + +A robust, interactive Bash script designed to securely synchronize SAP instance directories (such as `ASCS` and primary application servers) across environments using `rsync`. + +## ๐ŸŒŸ Features + +* **Interactive Execution:** Prompts the user before synchronizing each directory, allowing for granular control. +* **Dry-Run Mode:** Includes a `--dry-run` flag to simulate the transfer and safely review what will be copied or deleted without making actual changes. +* **Comprehensive Logging:** Automatically generates timestamped log files capturing both standard output and errors. +* **Strict Error Handling:** Captures pipeline errors accurately and aborts subsequent synchronizations if a directory fails, preventing inconsistent partial states. +* **Permission Preservation:** Utilizes `rsync` flags (`-aHAX`) specifically chosen to preserve critical SAP ACLs, extended attributes, and numeric IDs across systems. + +## ๐Ÿ“‹ Prerequisites + +* **OS:** Linux (Bash shell) +* **Packages:** `rsync` must be installed on both the source and target servers. +* **Access:** SSH passwordless access (key-based authentication) configured for the target user (e.g., `root`) to the target IP. + +## โš™๏ธ Configuration + +Before running the script, open it in your preferred text editor (like `vim` or `nano`) and adjust the variables at the top to match your environment: + + +``` + +```text +File generated successfully. + +```bash +TARGET_IP="10.84.242.225" # The destination server IP +TARGET_USER="root" # The user used for the SSH connection +SID="SP1" # The SAP System ID +LOG_DIR="/var/log/sap_sync" # Directory where logs will be stored + +``` + +*Note: Ensure the user executing the script has write permissions to the `LOG_DIR`.* + +## ๐Ÿš€ Usage + +### 1. Make the script executable + +First, ensure the script has the correct execute permissions: + +```bash +chmod +x sync_script.sh + +``` + +### 2. Standard Execution + +Run the script interactively. It will pause and ask for confirmation before syncing each path defined in the `directories` array. + +```bash +./sync_script.sh + +``` + +### 3. Dry-Run Execution (Recommended for first use) + +Test the synchronization safely. This will output exactly what rsync *would* do without transferring any data. + +```bash +./sync_script.sh --dry-run + +``` + +## ๐Ÿ“‚ Targeted Directories + +By default, the script is configured to synchronize the following standard NetWeaver/ABAP paths: + +* `/usr/sap//ASCS01/sec/` +* `/usr/sap//D00/sec/` +* `/usr/sap//D00/log/` +* `/sapmnt//` + +You can modify the `directories` array in the script to add or remove paths as needed. + +## ๐Ÿ“ Logging + +Logs are automatically stored in `/var/log/sap_sync/` (or your configured `LOG_DIR`). +Each run creates a unique file formatted as `sync_YYYYMMDD_HHMMSS.log`. You can review these logs for auditing purposes or to troubleshoot any failed transfers. diff --git a/SysInfoProject/SAP/SAP_RSYNC/sap_sync_dirs.sh b/SysInfoProject/SAP/SAP_RSYNC/sap_sync_dirs.sh new file mode 100644 index 0000000..31c5299 --- /dev/null +++ b/SysInfoProject/SAP/SAP_RSYNC/sap_sync_dirs.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# ========================================== +# Configuration & Variables +# ========================================== +TARGET_IP="10.84.242.225" +TARGET_USER="root" +SID="SP1" +LOG_DIR="/var/log/sap_sync" # Ensure this directory exists or change to /tmp +LOG_FILE="${LOG_DIR}/sync_$(date +%Y%m%d_%H%M%S).log" +DRY_RUN=false + +# Create log directory if it doesn't exist +mkdir -p "$LOG_DIR" + +# ========================================== +# Parameter Parsing +# ========================================== +# Check if the --dry-run flag was passed when executing the script +if [[ "$1" == "--dry-run" ]]; then + DRY_RUN=true + echo "==========================================" + echo " โ„น๏ธ RUNNING IN DRY-RUN MODE" + echo " No actual files will be transferred/deleted." + echo "==========================================" + echo +fi + +# ========================================== +# Arrays (Targets & Options) +# ========================================== +directories=( + "/usr/sap/${SID}/ASCS01/sec/" + "/usr/sap/${SID}/D00/sec/" + "/usr/sap/${SID}/D00/log/" + "/sapmnt/${SID}/" +) + +rsync_opts=( + -aHAXv + --numeric-ids + --delete + --progress +) + +# Append the dry-run flag to rsync options if enabled +if [ "$DRY_RUN" = true ]; then + rsync_opts+=("--dry-run") +fi + +# ========================================== +# Functions +# ========================================== + +# Standardized logging function +log_message() { + local msg="$1" + # Print to console and append to log file simultaneously + echo "$(date '+%Y-%m-%d %H:%M:%S') | $msg" | tee -a "$LOG_FILE" +} + +# Error handler +handle_error() { + local failed_dir="$1" + echo + log_message "โŒ ERROR: Synchronization failed on directory: $failed_dir" + log_message "โš ๏ธ Script aborted to prevent partial state issues." + exit 1 +} + +# ========================================== +# Main Execution Loop +# ========================================== +log_message "๐Ÿš€ Starting synchronization script..." +log_message "Target: ${TARGET_USER}@${TARGET_IP}" +log_message "Logging output to: $LOG_FILE" + +for dir in "${directories[@]}"; do + echo + log_message "โ–ถ๏ธ Queued target: $dir" + + read -p "Press Enter or type 'y' to run (any other key to abort): " choice + + if [[ -n "$choice" && ! "$choice" =~ ^[Yy]([Ee][Ss])?$ ]]; then + log_message "๐Ÿ›‘ Stopped by user before syncing: $dir" + exit 1 + fi + + log_message "โณ Synchronizing $dir..." + + # Execute rsync. + # 2>&1 redirects stderr to stdout so we capture errors in the log file. + # We pipe to 'tee -a' to show progress on screen and save it to the log. + rsync "${rsync_opts[@]}" "$dir" "${TARGET_USER}@${TARGET_IP}:${dir}" 2>&1 | tee -a "$LOG_FILE" + + # Capture the exit status of the rsync command, NOT the tee command. + # PIPESTATUS[0] holds the exit code of the first command in the pipe. + if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + handle_error "$dir" + fi + + log_message "โœ… Successfully completed: $dir" +done + +echo +log_message "๐ŸŽ‰ All directories synchronized successfully." diff --git a/SysInfoProject/SAP/SWPM/README.md b/SysInfoProject/SAP/SWPM/README.md new file mode 100644 index 0000000..d8e78e2 --- /dev/null +++ b/SysInfoProject/SAP/SWPM/README.md @@ -0,0 +1,36 @@ +# SAPinst Execution Wrapper + +A robust Bash script designed to automate and simplify the execution of the SAP Software Provisioning Manager (`sapinst`). This script handles remote access configuration, Certificate Revocation List (CRL) validation, and environment pre-checks. + +## ๐Ÿš€ Features + +* **Pre-execution Validation:** Ensures the `sapinst` binary and necessary CRL files are present before attempting execution, preventing partial starts or confusing installer errors. +* **Dynamic Hostname Detection:** Automatically detects the server's short hostname to configure the GUI hostname parameter accurately. +* **Remote GUI Configuration:** Pre-configures trusted remote access for a specific user. +* **Clear Logging & Error Handling:** Provides emoji-based console outputs for quick visual feedback and captures/returns standard exit codes. + +## ๐Ÿ“‹ Prerequisites + +Before running this script, ensure the following conditions are met: + +1. **Location:** The script must be placed and run from the same directory as the `sapinst` executable. +2. **Permissions:** The script requires execution permissions (`chmod +x run_sapinst.sh`). You must also have the appropriate OS permissions (usually `root`) to run SAPinst. +3. **CRL File:** Ensure the CRL file (`crlbag.p7s`) has been downloaded and placed in the directory specified by the `SAPINST_CRL_PATH` variable. + +## โš™๏ธ Configuration + +The script contains several hardcoded variables at the top of the file. You should modify these to match your specific environment and user requirements before running: + +| Variable | Description | Default Value | +| :--- | :--- | :--- | +| `SAPINST_USER` | The OS user permitted to remotely access the SAP GUI. | `mgveliz` | +| `SAPINST_TRUSTED` | Designates if the remote user is trusted. | `true` | +| `SAPINST_CRL_PATH` | Absolute path to the local CRL file. | `/usr/sap/trans/MGW_Files/MGWADM/swpm/crlbag.p7s` | +| `SAPINST_INST` | Absolute path to the SWPM installation directory. | `/usr/sap/trans/MGW_Files/MGWADM/swpm/INST_DIR` | +| `SAPINST_CRL_SOURCE_URL` | The remote source URL for the CRL validation. | `https://tcs.mysap.com/crl/crlbag.p7s` | + +## ๐Ÿ’ป Usage + +1. Navigate to the directory containing your unpacked SWPM/sapinst files: + ```bash + cd /path/to/swpm/ diff --git a/SysInfoProject/SAP/SWPM/sapinst.ps1 b/SysInfoProject/SAP/SWPM/sapinst.ps1 new file mode 100644 index 0000000..435f622 --- /dev/null +++ b/SysInfoProject/SAP/SWPM/sapinst.ps1 @@ -0,0 +1,15 @@ +# Define variables +$SapinstPath = "K:\The_SWPM\SWPM10SP45_2\sapinst.exe" +$RemoteAccessUser = "SPROPANE\sapbasis1" +$IsTrusted = "true" +$CrlPath = "K:\The_SWPM\crlbag_DEC_02_25.p7s" +$BrowserPath = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" +$CrlSourceUrl = "https://tcs.mysap.com/crl/crlbag.p7s" + +# Execute sapinst with parameters +& $SapinstPath ` + SAPINST_REMOTE_ACCESS_USER=$RemoteAccessUser ` + SAPINST_REMOTE_ACCESS_USER_IS_TRUSTED=$IsTrusted ` + SAPINST_CRL_PATH=$CrlPath ` + SAPINST_BROWSER="$BrowserPath" ` + SAPINST_CRL_SOURCE_URL="$CrlSourceUrl" diff --git a/SysInfoProject/SAP/SWPM/sapinst_run.sh b/SysInfoProject/SAP/SWPM/sapinst_run.sh new file mode 100644 index 0000000..fe35c1d --- /dev/null +++ b/SysInfoProject/SAP/SWPM/sapinst_run.sh @@ -0,0 +1,45 @@ + +#!/bin/bash +# Script to run sapinst with remote access and CRL path configuration +# Includes error handling and short hostname detection + +# Variables +SAPINST_USER="mgveliz" +SAPINST_TRUSTED="true" +SAPINST_CRL_PATH="/usr/sap/trans/MGW_Files/MGWADM/swpm/crlbag.p7s" +SAPINST_INST="/usr/sap/trans/MGW_Files/MGWADM/swpm/INST_DIR" +SAPINST_CRL_SOURCE_URL="https://tcs.mysap.com/crl/crlbag.p7s" + +# Get short hostname (without domain) +HOSTNAME=$(hostname -s) + +echo "โ„น๏ธ Running on server: $HOSTNAME" + +# Check if sapinst binary exists +if [[ ! -x "./sapinst" ]]; then + echo "โŒ Error: sapinst executable not found in current directory." + exit 1 +fi + +# Check if CRL file exists +if [[ ! -f "$SAPINST_CRL_PATH" ]]; then + echo "โŒ Error: CRL file not found at $SAPINST_CRL_PATH" + exit 2 +fi + +# Run sapinst +echo "โœ… Starting sapinst on $HOSTNAME..." +./sapinst SAPINST_REMOTE_ACCESS_USER="$SAPINST_USER" \ + SAPINST_REMOTE_ACCESS_USER_IS_TRUSTED="$SAPINST_TRUSTED" \ + SAPINST_CRL_SOURCE_URL="$SAPINST_CRL_SOURCE_URL" \ + SAPINST_INST="$SAPINST_INST" \ + SAPINST_GUI_HOSTNAME="$HOSTNAME" + +# Capture exit code +EXIT_CODE=$? +if [[ $EXIT_CODE -ne 0 ]]; then + echo "โŒ sapinst failed on $HOSTNAME with exit code $EXIT_CODE" + exit $EXIT_CODE +else + echo "โœ… sapinst completed successfully on $HOSTNAME." +fi diff --git a/SysInfoProject/SAP/find_sapstar_param.sh b/SysInfoProject/SAP/find_sapstar_param.sh new file mode 100644 index 0000000..21218a9 --- /dev/null +++ b/SysInfoProject/SAP/find_sapstar_param.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Usage function +usage() { + echo "Usage: $0 [--detailed]" + echo "Example: $0 PRD --detailed" + exit 1 +} + +# Check arguments +if [ -z "$1" ]; then + usage +fi + +SID=$1 +DETAILED=false + +# Check for optional --detailed flag +if [ "$2" == "--detailed" ]; then + DETAILED=true +fi + +PROFILE_DIR="/usr/sap/${SID}/SYS/profile" + +# Check if directory exists +if [ ! -d "$PROFILE_DIR" ]; then + echo "Profile directory not found: $PROFILE_DIR" + exit 2 +fi + +echo "Searching for 'login/no_automatic_user_sapstar' in profile files under ${PROFILE_DIR}..." +echo + +# Loop through all profile files +for file in "$PROFILE_DIR"/*; do + if [ -f "$file" ]; then + matches=$(grep -n "login/no_automatic_user_sapstar" "$file") + if [ -n "$matches" ]; then + echo "Found in: $(basename "$file")" + while IFS= read -r line; do + line_num=$(echo "$line" | cut -d: -f1) + param_line=$(echo "$line" | cut -d: -f2-) + value=$(echo "$param_line" | awk -F= '{gsub(/ /, "", $2); print $2}') + + echo " Line $line_num" + if [ "$DETAILED" = true ]; then + echo " $param_line" + fi + + if [ "$value" == "0" ]; then + echo " โžค SAP* is ENABLED (value = 0)" + elif [ "$value" == "1" ]; then + echo " โžค SAP* is DISABLED (value = 1)" + else + echo " โžค Unknown value: '$value' โ€” please verify manually" + fi + done <<< "$matches" + echo + fi + fi +done diff --git a/SysInfoProject/SAPROUTER/README.md b/SysInfoProject/SAPROUTER/README.md new file mode 100644 index 0000000..6cbefc2 --- /dev/null +++ b/SysInfoProject/SAPROUTER/README.md @@ -0,0 +1,28 @@ +# SAProuter Management Script + +This repository provides a **Bash script** to manage SAProuter with full lifecycle commands (`start`, `stop`, `status`, `restart`) and extended configuration options. + +--- + +## Features +- **Start/Stop/Status/Restart** SAProuter easily. +- Supports **trace level control**: + - `--no-trace` disables trace. + - `--trace-level ` sets custom trace level. +- Includes **extended SAProuter options**: + - `-r` : Run as router. + - `-Y 0` : Disable timeout for inactive connections. + - `-C 1000` : Maximum number of clients. + - `-D` : Run as daemon. + - `-J 20000000` : Jump buffer size. + - `-W 10000` : Maximum waiting connections. + - `-K ""` : Use specified certificate. +- **Logging**: Output stored in `saprouter.log`. +- **PID management**: PID stored in `saprouter.pid`. + +--- + +## Usage + +```bash +saprouter_manager.sh {start|stop|status|restart} [OPTIONS] diff --git a/SysInfoProject/SAPROUTER/saprouter_manager.sh b/SysInfoProject/SAPROUTER/saprouter_manager.sh new file mode 100644 index 0000000..31fa5ad --- /dev/null +++ b/SysInfoProject/SAPROUTER/saprouter_manager.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# saprouter_manager.sh +# Purpose: Manage SAProuter (start, stop, status, restart) with extended options + +# Variables +SAPROUTER_BIN="/usr/sap/SR1/saprouter/saprouter" +LOG_DIR="/usr/sap/SR1/saprouter/log" +PID_FILE="/usr/sap/SR1/saprouter/saprouter.pid" +MAX_CONN=10000 +CERT="p:CN=hhd-tfsrt01, OU=0000706563, OU=SAProuter, O=SAP, C=DE" + +# Defaults +TRACE_LEVEL=3 +ENABLE_TRACE=true + +# Usage function +usage() { + echo "Usage: $0 {start|stop|status|restart} [OPTIONS]" + echo + echo "Options:" + echo " --no-trace Disable trace level" + echo " --trace-level Set custom trace level (default: 3)" + echo " --help Show this help message" + echo + echo "Examples:" + echo " $0 start Start SAProuter with default trace level" + echo " $0 start --no-trace Start SAProuter without trace" + echo " $0 start --trace-level 2" + exit 0 +} + +# Parse command +ACTION="$1" +shift || true + +# Parse options +while [[ $# -gt 0 ]]; do + case "$1" in + --no-trace) + ENABLE_TRACE=false + shift + ;; + --trace-level) + TRACE_LEVEL="$2" + shift 2 + ;; + --help) + usage + ;; + *) + echo "Invalid option: $1" + usage + ;; + esac +done + +# Ensure log directory exists +mkdir -p "$LOG_DIR" + +# Functions +start_saprouter() { + if [[ -f "$PID_FILE" ]] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then + echo "SAProuter is already running with PID $(cat $PID_FILE)" + exit 0 + fi + + CMD="$SAPROUTER_BIN -r -Y 0 -C 1000 -D -J 20000000 -W $MAX_CONN -K \"$CERT\"" + if $ENABLE_TRACE; then + CMD="$CMD -V $TRACE_LEVEL" + fi + + echo "Starting SAProuter..." + nohup bash -c "$CMD" >> "$LOG_DIR/saprouter.log" 2>&1 & + echo $! > "$PID_FILE" + echo "SAProuter started with PID $(cat $PID_FILE)" +} + +stop_saprouter() { + if [[ -f "$PID_FILE" ]] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then + echo "Stopping SAProuter..." + kill $(cat "$PID_FILE") + rm -f "$PID_FILE" + echo "SAProuter stopped." + else + echo "SAProuter is not running." + fi +} + +status_saprouter() { + if [[ -f "$PID_FILE" ]] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then + echo "SAProuter is running with PID $(cat $PID_FILE)" + else + echo "SAProuter is not running." + fi +} + +restart_saprouter() { + stop_saprouter + sleep 2 + start_saprouter +} + +# Execute action +case "$ACTION" in + start) + start_saprouter + ;; + stop) + stop_saprouter + ;; + status) + status_saprouter + ;; + restart) + restart_saprouter + ;; + *) + usage + ;; +esac diff --git a/SysInfoProject/WIND/FindProcess/ps_fins.ps1 b/SysInfoProject/WIND/FindProcess/ps_fins.ps1 new file mode 100644 index 0000000..3b75645 --- /dev/null +++ b/SysInfoProject/WIND/FindProcess/ps_fins.ps1 @@ -0,0 +1,14 @@ + +# Define the process names to check +$processNames = @("R3load", "R3ldctl", "SAPuptool", "R3szchk") + +# Get all processes matching the names +$runningProcesses = Get-Process | Where-Object { $processNames -contains $_.ProcessName } + +# Display results +if ($runningProcesses) { + Write-Host "The following processes are running:" -ForegroundColor Green + $runningProcesses | Select-Object ProcessName, Id +} else { + Write-Host "None of the specified processes are running." -ForegroundColor Yellow +} diff --git a/SysInfoProject/WIND/Finding_files_PS1/README.md b/SysInfoProject/WIND/Finding_files_PS1/README.md new file mode 100644 index 0000000..4436ae9 --- /dev/null +++ b/SysInfoProject/WIND/Finding_files_PS1/README.md @@ -0,0 +1,26 @@ + +# PowerShell Script: Find Largest Files and Folders + +This PowerShell script helps you identify the **largest files and folders** in a specified directory. It is interactive and allows you to: + +- Enter the **target directory path** +- Filter files by **minimum size (in MB)** +- Specify how many **top items** to display +- View results for both **files and folders** + +--- + +## Features +โœ” Interactive prompts for directory, size filter, and number of items +โœ” Displays **largest files** and **largest folders** separately +โœ” Sizes shown in **MB** +โœ” Works recursively through subdirectories + +--- + +## Usage + +### 1. Clone the repository +```bash +git clone https://github.com/yourusername/largest-files-folders.git +cd largest-files-folders diff --git a/SysInfoProject/WIND/Finding_files_PS1/find_files_size.PS1 b/SysInfoProject/WIND/Finding_files_PS1/find_files_size.PS1 new file mode 100644 index 0000000..57a51e1 --- /dev/null +++ b/SysInfoProject/WIND/Finding_files_PS1/find_files_size.PS1 @@ -0,0 +1,32 @@ +# Prompt user for inputs +$directory = Read-Host "Enter the target directory path" +$minSizeMB = Read-Host "Enter minimum file size in MB (e.g., 500)" +$topCount = Read-Host "Enter how many top items to display (e.g., 10)" + +# Convert minimum size to bytes +$minSizeBytes = [math]::Round($minSizeMB * 1MB) + +Write-Host "`n--- Largest Files ---`n" + +# Get largest files meeting criteria +$largestFiles = Get-ChildItem -Path $directory -Recurse -File | + Where-Object { $_.Length -ge $minSizeBytes } | + Sort-Object Length -Descending | + Select-Object FullName, @{Name="Size(MB)";Expression={[math]::Round($_.Length / 1MB, 2)}} -First $topCount + +$largestFiles | Format-Table -AutoSize + +Write-Host "`n--- Largest Folders ---`n" + +# Calculate folder sizes +$largestFolders = Get-ChildItem -Path $directory -Directory | + ForEach-Object { + $folderSize = (Get-ChildItem -Path $_.FullName -Recurse -File | Measure-Object -Property Length -Sum).Sum + [PSCustomObject]@{ + Folder = $_.FullName + SizeMB = [math]::Round($folderSize / 1MB, 2) + } + } | + Sort-Object SizeMB -Descending | + Select-Object -First $topCount + diff --git "a/SysInfoProject/Windows/One\342\200\221liner_Script.txt" "b/SysInfoProject/Windows/One\342\200\221liner_Script.txt" new file mode 100644 index 0000000..ad321cb --- /dev/null +++ "b/SysInfoProject/Windows/One\342\200\221liner_Script.txt" @@ -0,0 +1 @@ +$y=2026; mkdir $y; 1..12 | % { mkdir ("{0}\{1:D2}" -f $y, $_) } diff --git a/SysInfoProject/Windows/mkdir_YYYY_MM.ps1 b/SysInfoProject/Windows/mkdir_YYYY_MM.ps1 new file mode 100644 index 0000000..44e247f --- /dev/null +++ b/SysInfoProject/Windows/mkdir_YYYY_MM.ps1 @@ -0,0 +1,14 @@ +param ( + [int]$Year +) + +# Create the year directory +New-Item -ItemType Directory -Name $Year -Force | Out-Null + +# Create month subdirectories (01โ€“12) +1..12 | ForEach-Object { + $month = "{0:D2}" -f $_ + New-Item -ItemType Directory -Path "$Year\$month" -Force | Out-Null +} + +Write-Host "Directory structure created for year $Year" diff --git a/SysInfoProject/Windows/rename_files/README.md b/SysInfoProject/Windows/rename_files/README.md new file mode 100644 index 0000000..6c512d3 --- /dev/null +++ b/SysInfoProject/Windows/rename_files/README.md @@ -0,0 +1,72 @@ +# Rename Spaces to Underscores (PowerShell) + +A PowerShell script to **recursively rename files and folders**, replacing spaces (" ") with underscores ("_"), with **dry-run**, **logging**, and **undo** capabilities. + +--- + +## โœจ Features + +- โœ… Renames **files and directories** +- โœ… Recursive operation +- โœ… **Dry-run mode** (preview changes safely) +- โœ… **Timestamped CSV log files** +- โœ… **Undo (redo)** support using the latest log +- โœ… Safe for deeply nested folder structures +- โœ… Built-in PowerShell help (`Get-Help` supported) + +--- + +## ๐Ÿš€ Usage + +### Preview changes (Dry-Run) +```powershell +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" -DryRun +``` + +### Perform renaming +```powershell +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" +``` + +### Undo last rename (Preview) +```powershell +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" -Undo -DryRun +``` + +### Undo last rename (Execute) +```powershell +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" -Undo +``` + +--- + +## ๐Ÿงพ Logging + +Each run creates a timestamped log file: +``` +rename_log_YYYYMMDD_HHMMSS.csv +``` + +The log is required for undo operations. + +--- + +## ๐Ÿ“– Builtโ€‘in Help + +```powershell +Get-Help .\Rename-SpacesToUnderscore.ps1 -Examples +``` + +--- + +## โš ๏ธ Best Practices + +- Always run with `-DryRun` first +- Keep log files until changes are verified +- Do not run multiple instances in parallel + +--- + +## ๐Ÿ“„ License + +MIT License diff --git a/SysInfoProject/Windows/rename_files/Rename-SpacesToUnderscore.ps1 b/SysInfoProject/Windows/rename_files/Rename-SpacesToUnderscore.ps1 new file mode 100644 index 0000000..a55de80 --- /dev/null +++ b/SysInfoProject/Windows/rename_files/Rename-SpacesToUnderscore.ps1 @@ -0,0 +1,147 @@ +<# +.SYNOPSIS +Renames files and folders by replacing spaces with underscores. + +.DESCRIPTION +This script recursively renames files and directories by replacing +blank spaces (" ") with underscores ("_"). + +Features: +- Works on files AND folders +- Recursive +- Timestamped CSV log file +- Dry-run mode (preview only) +- Undo (redo) capability using the latest log file + +.PARAMETER Path +The root directory to process. +Default is the current directory. + +.PARAMETER DryRun +Preview all rename operations without making any changes. + +.PARAMETER Undo +Reverts the most recent rename operation using the latest log file. +Can be combined with -DryRun. + +.EXAMPLE +Preview changes only: +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" -DryRun + +.EXAMPLE +Perform renaming: +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" + +.EXAMPLE +Preview undo: +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" -Undo -DryRun + +.EXAMPLE +Undo last rename: +.\Rename-SpacesToUnderscore.ps1 -Path "C:\Data" -Undo + +.NOTES +Author: Your Name +Log files are stored in the target Path. +Undo relies entirely on the latest rename_log_*.csv file. +Always run DryRun before executing changes in production. +#> + +param ( + [string]$Path = ".", + [switch]$Undo, + [switch]$DryRun +) + +# Timestamp for log file +$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss" +$LogFile = Join-Path $Path "rename_log_$Timestamp.csv" + +# ========================= +# UNDO MODE +# ========================= +if ($Undo) { + $LatestLog = Get-ChildItem -Path $Path -Filter "rename_log_*.csv" | + Sort-Object LastWriteTime -Descending | + Select-Object -First 1 + + if (-not $LatestLog) { + Write-Error "No log file found to undo." + exit 1 + } + + Import-Csv $LatestLog.FullName | + Sort-Object Depth | + ForEach-Object { + if (Test-Path $_.NewPath) { + if ($DryRun) { + Write-Host "[DRY-RUN] Rename $($_.NewPath) -> $($_.OldPath)" + } else { + Rename-Item -Path $_.NewPath -NewName (Split-Path $_.OldPath -Leaf) + } + } + } + + Write-Host "Undo completed using log: $($LatestLog.Name)" + exit +} + +# ========================= +# RENAME MODE +# ========================= +$log = @() + +# Rename directories (deepest first) +Get-ChildItem -Path $Path -Recurse -Directory | +Sort-Object FullName -Descending | +ForEach-Object { + if ($_.Name -match ' ') { + $newName = $_.Name -replace ' ', '_' + $newPath = Join-Path $_.Parent.FullName $newName + + if ($DryRun) { + Write-Host "[DRY-RUN] Rename DIR : $($_.FullName) -> $newPath" + } else { + Rename-Item $_.FullName $newName + } + + $log += [pscustomobject]@{ + OldPath = $_.FullName + NewPath = $newPath + Depth = $_.FullName.Split('\').Count + Type = "Directory" + } + } +} + +# Rename files +Get-ChildItem -Path $Path -Recurse -File | +ForEach-Object { + if ($_.Name -match ' ') { + $newName = $_.Name -replace ' ', '_' + $newPath = Join-Path $_.DirectoryName $newName + + if ($DryRun) { + Write-Host "[DRY-RUN] Rename FILE : $($_.FullName) -> $newPath" + } else { + Rename-Item $_.FullName $newName + } + + $log += [pscustomobject]@{ + OldPath = $_.FullName + NewPath = $newPath + Depth = $_.FullName.Split('\').Count + Type = "File" + } + } +} + +# Save log +$log | Export-Csv $LogFile -NoTypeInformation + +Write-Host "Operation completed." +Write-Host "Log saved as: $LogFile" + +if ($DryRun) { + Write-Host "No files or folders were actually renamed (DRY-RUN)." +} diff --git a/SysInfoProject/X11/setup_x11_forwarding.sh b/SysInfoProject/X11/setup_x11_forwarding.sh new file mode 100644 index 0000000..9bfde02 --- /dev/null +++ b/SysInfoProject/X11/setup_x11_forwarding.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +TARGET_USER="$1" + +if [ -z "$TARGET_USER" ]; then + echo "โŒ Error: No target user specified." + echo "Usage: $0 " + exit 1 +fi + +# Usar :10 como valor por defecto si DISPLAY no estรก definido +DISPLAY_VAL="${DISPLAY:-:10}" + +if [ -z "$DISPLAY_VAL" ]; then + echo "โŒ Error: DISPLAY environment variable is not set." + exit 2 +fi + +# Obtener el cookie de xauth para el DISPLAY actual +COOKIE=$(xauth list "$DISPLAY_VAL" 2>/dev/null | head -n 1) + +if [ -z "$COOKIE" ]; then + echo "โŒ Error: No xauth cookie found for DISPLAY=$DISPLAY_VAL" + exit 3 +fi + +# Guardar el cookie en archivo temporal +echo "$COOKIE" > /tmp/z_xauth +if [ $? -ne 0 ]; then + echo "โŒ Error: Failed to write xauth cookie to /tmp/z_xauth" + exit 4 +fi + +# Verificar si sudo estรก disponible +if ! command -v sudo &> /dev/null; then + echo "โŒ Error: 'sudo' command not found. Cannot switch user to $TARGET_USER." + rm -f /tmp/z_xauth + exit 5 +fi + +# Verificar si el usuario actual tiene permisos para usar sudo con el usuario objetivo +if ! sudo -l -U "$USER" | grep -q "(ALL) NOPASSWD: ALL"; then + echo "โš ๏ธ Advertencia: Puede que se requiera contraseรฑa para ejecutar comandos como $TARGET_USER." +fi + +# Ejecutar como el usuario objetivo +sudo -u "$TARGET_USER" bash < /dev/null; then + echo "โŒ Error: xauth not found for user $TARGET_USER" + exit 6 + fi + + xauth add $COOKIE + echo "โœ… xauth list for $TARGET_USER:" + xauth list +EOF + +# Verificar si el comando sudo fue exitoso +if [ $? -ne 0 ]; then + echo "โŒ Error: Failed to execute xauth commands as user '$TARGET_USER'." + rm -f /tmp/z_xauth + exit 7 +fi + +# Limpiar archivo temporal +rm -f /tmp/z_xauth + +echo "โœ… X11 forwarding setup complete for user '$TARGET_USER'." diff --git a/SysInfoProject/mem_monitor/RAM/README.md b/SysInfoProject/mem_monitor/RAM/README.md new file mode 100644 index 0000000..7739b34 --- /dev/null +++ b/SysInfoProject/mem_monitor/RAM/README.md @@ -0,0 +1,27 @@ +# top-ram.sh + +`top-ram.sh` is a Bash script that displays the top processes consuming the most **RAM (Resident Set Size - VmRSS)** on a Linux system. It provides detailed information including PID, process name, RAM usage in kilobytes, and the full command line used to launch the process. + +## Features + +- Lists processes using RAM, sorted by usage. +- Supports filtering by: + - Specific usernames (`-u` or `--user`) + - Specific UIDs (`-U` or `--uid`) + - Current user only (`--mine`) +- Output options: + - Pretty-printed table (default) + - Tab-separated values (`--tsv`) +- Show top N processes (`-n`) +- Show all processes with non-zero RAM usage (`--all`) +- Optionally include a user column (`--show-user`) + +## Requirements + +- Bash 4+ +- Standard Unix utilities: `awk`, `sort`, `head`, `tr`, `id`, `getent` + +## Usage + + +bash ./top-ram.sh diff --git a/SysInfoProject/mem_monitor/RAM/top-ram.sh b/SysInfoProject/mem_monitor/RAM/top-ram.sh new file mode 100644 index 0000000..dd9d539 Binary files /dev/null and b/SysInfoProject/mem_monitor/RAM/top-ram.sh differ diff --git a/SysInfoProject/mem_monitor/SWAP/README.md b/SysInfoProject/mem_monitor/SWAP/README.md new file mode 100644 index 0000000..e56e8de --- /dev/null +++ b/SysInfoProject/mem_monitor/SWAP/README.md @@ -0,0 +1,40 @@ +# top-swap.sh โ€” Top processes by swap usage (with full command lines) + +`top-swap.sh` scans `/proc` to show the **top processes by swap usage** on Linux, including **PID**, **Name**, optional **User**, **Swap (kB)**, and the **full command line**. Itโ€™s efficient (reads `cmdline` only for the top entries) and supports user filtering and machine-friendly TSV output. + +--- + +## โœจ Features + +- ๐Ÿ”Ž Shows **PID**, **Name**, **Swap (kB)**, and **full command line** +- ๐Ÿ‘ค Optional **User** column with `--show-user` +- ๐Ÿ” **User filtering**: `--mine`, `-u user1[,user2]`, `-U uid1[,uid2]` +- ๐Ÿงฎ Choose **top N** with `-n N` or show **all** with `--all` +- ๐Ÿ“„ **TSV output** (`--tsv`) for scripting +- ๐Ÿงต Gracefully handles kernel threads / unreadable `cmdline` (prints `[Name]`) +- ๐Ÿš€ Designed for speed: reads `/proc//cmdline` **only** for top rows + +--- + +## ๐Ÿงฉ Requirements + +- **Linux** with `/proc` mounted +- **Bash 4+** (associative arrays) +- Tools: `awk`, `sort`, `head`, `tr`, `id`, `getent` +- Permissions: You may need `sudo` on systems using `hidepid` or to read other usersโ€™ `cmdline` + +Check your Bash version: + +echo "$BASH_VERSION" + +## ๐Ÿงญ Usage + +./top-swap.sh +./top-swap.sh --show-user +./top-swap.sh --tsv | column -t -s $'\t' + +## ๐Ÿงช Examples + +./top-swap.sh -n 20 --show-user +./top-swap.sh --mine +sudo ./top-swap.sh -u postgres -U 0 --show-user diff --git a/SysInfoProject/mem_monitor/SWAP/top-swap.sh b/SysInfoProject/mem_monitor/SWAP/top-swap.sh new file mode 100644 index 0000000..98422b7 --- /dev/null +++ b/SysInfoProject/mem_monitor/SWAP/top-swap.sh @@ -0,0 +1,209 @@ +#!/usr/bin/env bash +# top-swap.sh โ€” Show top processes by swap usage with full command lines. +# Default: top 10. Use -n N to change. Use --tsv for tab-separated output. Use --all to show all. +# User filtering: --mine, -u/--user USER[,USER2], -U/--uid UID[,UID2] +# --show-user: include a User column (pretty & TSV) + +set -euo pipefail + +# Ensure Bash 4+ (associative arrays required) +if [[ -z "${BASH_VERSINFO:-}" || "${BASH_VERSINFO[0]}" -lt 4 ]]; then + echo "This script requires Bash 4+ (found: ${BASH_VERSION:-unknown}). Run with: bash $0 ..." >&2 + exit 1 +fi + +TOP=10 +OUTPUT="pretty" # "pretty" or "tsv" +SHOW_ALL=0 +SHOW_USER=0 + +# User filtering +ONLY_MINE=0 +declare -a USERS=() # usernames +declare -a UIDS=() # numeric UIDs + +usage() { + cat <<'EOF' +Usage: top-swap.sh [-n N] [--tsv] [--all] [--mine] [-u USER[,USER2] ...] [-U UID[,UID2] ...] [--show-user] [-h] + +Options: + -n N Show top N processes by swap (default: 10) + --tsv Output as tab-separated values + --all Show all processes with non-zero swap (no top limit) + --mine Show only processes owned by the current user (real UID) + -u, --user USER Filter by username (repeatable or comma-separated) + -U, --uid UID Filter by numeric UID (repeatable or comma-separated) + --show-user Include a User column (pretty & TSV) + -h Show this help + +Notes: + - Use 'bash ./top-swap.sh' (not 'sh'). Run with sudo if /proc is restricted. + - Filtering uses Real UID from /proc//status (Uid: line). + - Kernel threads or unreadable cmdlines are shown as [Name]. +EOF +} + +# Parse args +while [[ $# -gt 0 ]]; do + case "$1" in + -n) + [[ $# -ge 2 ]] || { echo "Error: -n requires a number" >&2; exit 1; } + TOP="$2"; shift 2;; + --tsv) + OUTPUT="tsv"; shift;; + --all) + SHOW_ALL=1; shift;; + --mine) + ONLY_MINE=1; shift;; + -u|--user) + [[ $# -ge 2 ]] || { echo "Error: $1 requires an argument" >&2; exit 1; } + IFS=',' read -r -a tmp_users <<< "$2"; USERS+=("${tmp_users[@]}"); shift 2;; + -U|--uid) + [[ $# -ge 2 ]] || { echo "Error: $1 requires an argument" >&2; exit 1; } + IFS=',' read -r -a tmp_uids <<< "$2"; UIDS+=("${tmp_uids[@]}"); shift 2;; + --show-user) + SHOW_USER=1; shift;; + -h|--help) + usage; exit 0;; + *) + echo "Unknown option: $1" >&2 + usage + exit 1;; + esac +done + +# Ensure required tools exist +for cmd in awk sort head tr id getent; do + command -v "$cmd" >/dev/null 2>&1 || { echo "Missing required command: $cmd" >&2; exit 1; } +done + +# Build the UID filter set +declare -A UID_SET=() +if [[ "$ONLY_MINE" -eq 1 ]]; then + UID_SET["$(id -u)"]=1 +fi + +# Loop only if arrays have elements (avoid empty element under set -u) +if ((${#USERS[@]})); then + for u in "${USERS[@]}"; do + if uid=$(id -u "$u" 2>/dev/null); then + UID_SET["$uid"]=1 + else + echo "Warning: user '$u' not found (skipping)" >&2 + fi + done +fi + +if ((${#UIDS[@]})); then + for uid in "${UIDS[@]}"; do + if [[ "$uid" =~ ^[0-9]+$ ]]; then + UID_SET["$uid"]=1 + else + echo "Warning: invalid UID '$uid' (skipping)" >&2 + fi + done +fi + +# Build a comma-separated filter string +UID_FILTER="" +for k in "${!UID_SET[@]}"; do + UID_FILTER+="${UID_FILTER:+,}$k" +done + +# Locale-neutral sort for numbers +export LC_ALL=C + +# Function to generate the raw list: \t\t\t +gen_list() { + awk -v uid_filter="$UID_FILTER" -F':' ' + BEGIN { + use_filter = (length(uid_filter) > 0) + if (use_filter) { + n = split(uid_filter, allow, /,/) + for (i=1; i<=n; i++) allow_uids[allow[i]] = 1 + } + } + FNR==1 { pid=""; name=""; swap=""; uid="" } # reset per file + { gsub(/^[ \t]+/, "", $2) } # trim leading spaces + $1=="Pid" { pid=$2; next } + $1=="Name" { name=$2; next } + $1=="Uid" { split($2, u, /[ \t]+/); uid=u[1]; next } # Real UID + $1=="VmSwap" { + if ($2 != "" && $2 != "0 kB") { + if (!use_filter || (uid in allow_uids)) { + split($2, v, /[ \t]+/) # v[1] = numeric kB + printf "%s\t%s\t%s\t%s\n", v[1], pid, uid, name + } + } + } + ' /proc/[0-9]*/status 2>/dev/null +} + +# Fetch and optionally limit top N +if [[ "$SHOW_ALL" -eq 1 ]]; then + mapfile -t LINES < <( gen_list | sort -k1,1nr ) +else + mapfile -t LINES < <( gen_list | sort -k1,1nr | head -n "$TOP" ) +fi + +# If no results, exit gracefully +if [[ ${#LINES[@]} -eq 0 ]]; then + if [[ -n "$UID_FILTER" ]]; then + echo "No processes with non-zero swap found for the specified user(s) or insufficient permissions." >&2 + else + echo "No processes with non-zero swap found (or insufficient permissions)." >&2 + fi + exit 0 +fi + +# Username cache for --show-user +declare -A USER_CACHE=() + +resolve_user() { + local uid="$1" + if [[ -n "${USER_CACHE[$uid]:-}" ]]; then + echo "${USER_CACHE[$uid]}"; return + fi + local name + name="$(getent passwd "$uid" | cut -d: -f1 || true)" + [[ -n "$name" ]] || name="#$uid" + USER_CACHE["$uid"]="$name" + echo "$name" +} + +# Header +if [[ "$OUTPUT" == "pretty" ]]; then + if [[ "$SHOW_USER" -eq 1 ]]; then + printf "%10s %-30s %-12s %12s %s\n" "PID" "Name" "User" "Swap(kB)" "Command" + else + printf "%10s %-30s %12s %s\n" "PID" "Name" "Swap(kB)" "Command" + fi +fi + +# Print rows: each line is \t\t\t +for line in "${LINES[@]}"; do + IFS=$'\t' read -r swap_kb pid uid name <<< "$line" + + # Read full cmdline; convert NULs to spaces + cmdline="" + if [[ -r "/proc/$pid/cmdline" ]]; then + cmdline="$(tr '\0' ' ' <"/proc/$pid/cmdline" 2>/dev/null || true)" + fi + [[ -n "$cmdline" ]] || cmdline="[$name]" + + if [[ "$OUTPUT" == "tsv" ]]; then + if [[ "$SHOW_USER" -eq 1 ]]; then + user="$(resolve_user "$uid")" + printf "%s\t%s\t%s\t%s\t%s\n" "$pid" "$name" "$user" "$swap_kb" "$cmdline" + else + printf "%s\t%s\t%s\t%s\n" "$pid" "$name" "$swap_kb" "$cmdline" + fi + else + if [[ "$SHOW_USER" -eq 1 ]]; then + user="$(resolve_user "$uid")" + printf "%10s %-30s %-12s %12s %s\n" "$pid" "$name" "$user" "$swap_kb" "$cmdline" + else + printf "%10s %-30s %12s %s\n" "$pid" "$name" "$swap_kb" "$cmdline" + fi + fi +done diff --git a/SysInfoProject/scrtips/functions.sh b/SysInfoProject/scrtips/functions.sh new file mode 100644 index 0000000..7de1fd3 --- /dev/null +++ b/SysInfoProject/scrtips/functions.sh @@ -0,0 +1,2 @@ +function pause(){ +function write_header(){ diff --git a/SysInfoProject/scrtips/main.sh b/SysInfoProject/scrtips/main.sh new file mode 100644 index 0000000..8671800 --- /dev/null +++ b/SysInfoProject/scrtips/main.sh @@ -0,0 +1,629 @@ +function os_info(){ +write_header " System information " +echo "Operating system : $(uname)" +[ -x $LSB ] && $LSB -a || echo "$LSB command is not insalled (set \$LSB variable)" +#pause "Press [Enter] key to continue..." +pause +} + +# Purpose - Get info about host such as dns, IP, and hostname +function host_info(){ +local dnsips=$(sed -e '/^$/d' /etc/resolv.conf | awk '{if (tolower($1)=="nameserver") print $2}') +write_header " Hostname and DNS information " +echo "Hostname : $(hostname -s)" +echo "DNS domain : $(hostname -d)" +echo "Fully qualified domain name : $(hostname -f)" +echo "Network address (IP) : $(hostname -i)" +echo "DNS name servers (DNS IP) : ${dnsips}" +pause +} + +# Purpose - Network inferface and routing info +function net_info(){ +devices=$(ss -i | cut -d" " -f1 | egrep -v "^Kernel|Iface|lo") +write_header " Network information " +echo "Total network interfaces found : $(wc -w <<<${devices})" + +echo "*** IP Addresses Information ***" +ip -4 address show + +echo "***********************" +echo "*** Network routing ***" +echo "***********************" +ss -r + +echo "**************************************" +echo "*** Interface traffic information ***" +echo "**************************************" +ss -i + +pause +} + +# Purpose - Display a list of users currently logged on +# display a list of receltly loggged in users +function user_info(){ +local cmd="$1" +case "$cmd" in +who) write_header " Who is online "; who -H; pause ;; +last) write_header " List of last logged in users "; last ; pause ;; +esac +} + +# Purpose - Display used and free memory info +function mem_info(){ +write_header " Free and used memory " +free -m + +echo "*********************************" +echo "*** Virtual memory statistics ***" +echo "*********************************" +vmstat +echo "***********************************" +echo "*** Top 5 memory eating process ***" +echo "***********************************" +ps auxf | sort -nr -k 4 | head -5 +pause +} + +# Purpose - Get Public IP address form your ISP +function ip_info(){ +cmd='curl -s' +write_header " Public IP information " +ipservice=checkip.dyndns.org +pipecmd=(sed -e 's/.*Current IP Address: //' -e 's/<.*$//') #using brackets to use it as an array and avoid need of scaping +$cmd "$ipservice" | "${pipecmd[@]}" +pause +} + +# purpose - Get Disk Usage Information +function disk_info() { +usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1) + partition=$(echo $output | awk '{print $2}') +write_header " Disk Usage Info" +if [ "$EXCLUDE_LIST" != "" ] ; then + df -H | grep -vE "^Filesystem|tmpfs|cdrom|${EXCLUDE_LIST}" | awk '{print $5 " " $6}' +else + df -H | grep -vE "^Filesystem|tmpfs|cdrom" | awk '{print $5 " " $6}' +fi +pause +} +#Purpose of Process Usage Information + +function proc_info() { +write_header " Process Usage Info" + + + +s %s\n" ' ' "$line" + done +} + +s %s\n" ' ' "$line" + done +} + +while : +do + +clear + +echo "" +echo "" +echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide +echo "" +echo "1. Show all processes" | center +echo "2. Kill a process" | center +echo "3. Bring up top" | center +echo "4. ${txtpur}Return to Main Menu${txtrst}" | center +echo "5. ${txtred}Shut down${txtrst}" | center +echo "" + +read processmenuchoice +case $processmenuchoice in + +1 ) + clear && echo "" && echo "${txtcyn}(press ENTER or use arrow keys to scroll list, press Q to return to menu)${txtrst}" | centerwide && read + ps -ef | less +;; + +2 ) + clear && echo "" && echo "Please enter the PID of the process you would like to kill:" | centerwide + read pidtokill + kill -2 $pidtokill && echo "${txtgrn}Process terminated successfully.${txtrst}" | center || echo "${txtred}Process failed to terminate. Please check the PID and try again.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +3 ) + top +;; + +4 ) + clear && echo "" && echo "Are you sure you want to return to the main menu? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read exitays + case $exitays in + y | Y ) + clear && exit + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + esac +;; + +5 ) + clear && echo "" && echo "Are you sure you want to shut down? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read shutdownays + case $shutdownays in + y | Y ) + clear && shutdown -h now + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +* ) + clear && echo "" && echo "${txtred}Please make a valid selection." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read +;; +esac + +done +pause +} + +#Purpose - For getting User operation and infrmations +function user_infos() { + +write_header "User Operations" + + + + +s %s\n" ' ' "$line" + done +} + +s %s\n" ' ' "$line" + done +} + +while : +do + +clear + +echo "" +echo "" +echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide +echo "" +echo "1. Create a user" | center +echo "2. Change the group for a user" | center +echo "3. Create a group" | center +echo "4. Delete a user" | center +echo "5. Change a password" | center +echo "6. ${txtpur}Return to Main Menu${txtrst}" | center +echo "7. ${txtred}Shut down${txtrst}" | center +echo "" + +read usermenuchoice +case $usermenuchoice in + +1 ) + clear && echo "" && echo "Please enter the new username below: ${txtcyn}(NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read newusername + echo "" && echo "Please enter a group for the new user: ${txtcyn}(STILL NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read newusergroup + echo "" && echo "What is the new user's full name? ${txtcyn}(YOU CAN USE SPACES HERE IF YOU WANT!)${txtrst}" | centerwide && echo "" + read newuserfullname + echo "" && echo "" + groupadd $newusergroup + useradd -g $newusergroup -c "$newuserfullname" $newusername && echo "${txtgrn}New user $newusername created successfully.${txtrst}" | center || echo "${txtred}Could not create new user.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +2 ) + clear && echo "" && echo "Which user needs to be in a different group? ${txtcyn}(USER MUST EXIST!)${txtrst}" | centerwide && echo "" + read usermoduser + echo "" && echo "What should be the new group for this user? ${txtcyn}(NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read usermodgroup + echo "" && echo "" + groupadd $usermodgroup + usermod -g $usermodgroup $usermoduser && echo "${txtgrn}User $usermoduser added to group $usermodgroup successfully.${txtrst}" | center || echo "${txtred}Could not add user to group. Please check if user exists.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +3 ) + clear && echo "" && echo "Please enter a name for the new group below: ${txtcyn}(NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read newgroup + echo "" && echo "" + groupadd $newgroup && echo "${txtgrn}Group $newgroup created successfully.${txtrst}" | center || echo "${txtred}Failed to create group. Please check if group already exists.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +4 ) + clear && echo "" && echo "Please enter the username to be deleted below: ${txtcyn}(THIS CANNOT BE UNDONE!)${txtrst}" | centerwide && echo "" + read deletethisuser + echo "" && echo "${txtred}ARE YOU ABSOLUTELY SURE YOU WANT TO DELETE THIS USER? SERIOUSLY, THIS CANNOT BE UNDONE! ${txtcyn}y/n${txtrst}" | centerwide + read deleteuserays + echo "" && echo "" + case $deleteuserays in + y | Y ) + if id "$deletethisuser" &>/dev/null; then + userdel "$deletethisuser" + log_action "Deleted user $deletethisuser" +else + echo "User $deletethisuser does not exist." +fi && echo "${txtgrn}User $deletethisuser deleted successfully." | center || echo "${txtred}Failed to delete user. Please check username and try again.${txtrst}" | centerwide + ;; + n | N ) + echo "Okay. Nevermind then." | center + ;; + * ) + echo "${txtred}Please make a valid selection.${txtrst}" | center + ;; + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +5 ) + clear && echo "" && echo "Which user's password should be changed?" | centerwide + read passuser + echo "" + passwd $passuser && echo "${txtgrn}Password for $passuser changed successfully.${txtrst}" | center || echo "${txtred}Failed to change password.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +6 ) + clear && echo "" && echo "Are you sure you want to return to the main menu? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read exitays + case $exitays in + y | Y ) + clear && exit + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +7 ) + clear && echo "" && echo "Are you sure you want to shut down? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read shutdownays + case $shutdownays in + y | Y ) + clear && shutdown -h now + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +* ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read +;; + +esac + +done +pause +} + +#Purpose - For File Opertios +function file_info() { +write_header "File OPerations" + + + +s %s\n" ' ' "$line" + done +} + +s %s\n" ' ' "$line" + done +} + +while : +do + +clear + +echo "" +echo "" +echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide +echo "" +echo "1. Create a file" | center +echo "2. Delete a file" | center +echo "3. Create a directory" | center +echo "4. Delete a directory" | center +echo "5. Create a symbolic link" | center +echo "6. Change ownership of a file" | center +echo "7. Change permissions on a file" | center +echo "8. Modify text within a file" | center +echo "9. Compress a file" | center +echo "10. Decompress a file" | center +echo "11. ${txtpur}Return to main menu${txtrst}" | center +echo "12. ${txtred}Shut down${txtrst}" | center +echo "" + +read mainmenuchoice +case $mainmenuchoice in + +1 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center + echo "" && echo "Please enter the ${txtcyn}full path${txtrst} and filename for the new file:" | centerwide && echo "" + echo "${txtcyn}(if file exists, it will be touched)${txtrst}" | center && echo "" + read touchfile + echo "" && echo "" + touch $touchfile && echo "${txtgrn}File $touchfile touched successfully.${txtrst}" | centerwide || echo "${txtred}Touch failed. How did you even do that?${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +2 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center && echo "" && ls && echo "" + echo "Please enter the ${txtcyn}full path${txtrst} and filename for the file to be deleted:" | centerwide && echo "" + read rmfile + echo "" && echo "" + if [[ -f "$rmfile" ]]; then + rm -i "$rmfile" + log_action "Deleted file $rmfile" +else + echo "File $rmfile does not exist." +fi && echo "${txtgrn}File removed successfully.${txtrst}" | center || echo "${txtred}File removal failed.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +3 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center && echo "" && ls && echo "" + echo "Please enter the ${txtcyn}full path${txtrst} for the directory to be created:" | centerwide && echo "" + read mkdirdir + echo "" && echo "" + mkdir $mkdirdir && echo "${txtgrn}Directory $mkdirdir created successfully.${txtrst}" | centerwide || echo "${txtred}Failed to create directory.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +4 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center && echo "" && ls && echo "" + echo "Please enter the ${txtcyn}full path${txtrst} for the directory to be removed: ${txtcyn}(MUST BE EMPTY!)${txtrst}" | centerwide && echo "" + read rmdirdir + echo "" && echo "" + rmdir $rmdirdir && echo "${txtgrn}Directory $rmdirdir removed successfully.${txtrst}" | centerwide || echo "${txtred}Failed to remove directory. Please ensure directory is empty.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +5 ) + clear && echo "" && echo "Please enter the input file for the symbolic link: ${txtcyn}(FULL PATH!)${txtrst}" | centerwide && echo "" + read symlinfile + echo "" && echo "Please enter the output file for the symbolic link: ${txtcyn}(SERIOUSLY, FULL PATH!)${txtrst}" | centerwide && echo "" + read symloutfile + echo "" && echo "" + +if [[ -e "$symlinfile" ]]; then + ln -s "$symlinfile" "$symloutfile" + if [[ -L "$symloutfile" ]]; then + echo "Symbolic link created successfully at $symloutfile" + log_action "Created symbolic link from $symlinfile to $symloutfile" + else + echo "Failed to create symbolic link." + fi +else + echo "Input file $symlinfile does not exist." +fi + cat $symloutfile && clear && echo "" && echo "${txtgrn}Symbolic link created successfully at $symloutfile${txtrst}" | centerwide || echo "${txtred}Failed to create symbolic link. Please check paths and filenames and try again.${txtrst}" | centerwide && rm -f $symloutfile + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +6 ) + clear && echo "" && echo "Which file's ownership should be changed? ${txtcyn}(MUST EXIST, USE FULL PATH!)${txtrst}" | centerwide && echo "" + read chownfile + echo "" && echo "Please enter the username for the new owner of $chownfile: ${txtcyn}(USER MUST EXIST)${txtrst}" | centerwide && echo "" + read chownuser + echo "" && echo "Please enter the new group for $chownfile: ${txtcyn}(GROUP MUST EXIST)${txtrst}" | centerwide && echo "" + read chowngroup + echo "" && echo "" + chown $chownuser.$chowngroup $chownfile && echo "${txtgrn}Ownership of $chownfile changed successfully.${txtrst}" | centerwide || echo "${txtred}Failed to change ownership. Please check if user, group and file exist.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +7 ) + clear && echo "" && echo "Which file's permissions should be changed? ${txtcyn}(MUST EXIST, USE FULL PATH!)${txtrst}" | centerwide && echo "" + read chmodfile + echo "" && echo "Please enter the three-digit numeric string for the permissions you would like to set:" | centerwide + echo "" + echo "${txtcyn}( format is [owner][group][all] | ex: ${txtrst}777${txtcyn} for full control for everyone )${txtrst}" | centerwide + echo "" + echo "${txtcyn}4 = read${txtrst}" | center + echo "${txtcyn}2 = write${txtrst}" | center + echo "${txtcyn}1 = execute${txtrst}" | center + echo "" + read chmodnum + echo "" && echo "" + chmod $chmodnum $chmodfile && echo "${txtgrn}Permissions for $chmodfile changed successfully.${txtrst}" | centerwide || echo "${txtred}Failed to set permissions.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +8 ) + clear && echo "" && echo "Please enter the full path and filename for the file you wish to edit:" | centerwide && echo "" + read editfile + echo "Which program would you like to use to edit this file?" | centerwide && echo "" + echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide + echo "1. vim" | center + echo "2. nano" | center + echo "3. mcedit" | center + echo "4. emacs" | center + echo "5. pico" | center + echo "" + read editapp + echo "" + case $editapp in + 1 ) + vim $editfile || echo "${txtred}Failed to open vim. Please check if it is installed.${txtrst}" | centerwide + ;; + + 2 ) + nano $editfile || echo "${txtred}Failed to open nano. Please check if it is installed.${txtrst}" | centerwide + ;; + + 3 ) + mcedit $editfile || echo "${txtred}Failed to open mcedit. Please check if it is installed.${txtrst}" | centerwide + ;; + + 4 ) + emacs $editfile || echo "${txtred}Failed to open emacs. Please check if it is installed.${txtrst}" | centerwide + ;; + + 5 ) + pico $editfile || echo "${txtred}Failed to open pico. Please check if it is installed.${txtrst}" | centerwide + ;; + + * ) + echo "${txtred}Please make a valid selection.${txtrst}" | center + ;; + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +9 ) + clear && echo "" && echo "Please enter the ${txtcyn}full path${txtrst} and filename for the file you wish to compress:" | centerwide && echo "" + read pressfile + echo "" && echo "Which method of compression would you like to use?" | centerwide && echo "" + echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide + echo "" + echo "1. gzip" | center + echo "2. bzip2" | center + echo "3. compress" | center + echo "" + read pressmethod + echo "" + case $pressmethod in + 1 ) + gzip $pressfile && echo "${txtgrn}File compressed successfully.${txtrst}" | center || echo "${txtred}File failed to compress.${txtrst}" | center + ;; + + 2 ) + bzip2 $pressfile && echo "${txtgrn}File compressed successfully.${txtrst}" | center || echo "${txtred}File failed to compress.${txtrst}" | center + ;; + + 3 ) + compress $pressfile && echo "${txtgrn}File compressed successfully.${txtrst}" | center || echo "${txtred}File failed to compress.${txtrst}" | center + ;; + + * ) + echo "${txtred}Please make a valid selection.${txtrst}" | center + ;; + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +10 ) + clear && echo "" && echo "Please enter the ${txtcyn}full path${txtrst} and filename for the file you wish to decompress:" | centerwide && echo "" + read depressfile + case $depressfile in + *.gz | *.GZ ) + gunzip $depressfiles && echo "${txtgrn}File decompressed successfully.${txtrst}" | center || echo "${txtred}File failed to decompress.${txtrst}" | center + ;; + + *.bz2 | *.BZ2 ) + bunzip2 $depressfile && echo "${txtgrn}File decompressed successfully.${txtrst}" | center || echo "${txtred}File failed to decompress.${txtrst}" | center + ;; + + *.z | *.Z ) + uncompress $depressfile && echo "${txtgrn}File decompressed successfully.${txtrst}" | center || echo "${txtred}File failed to decompress.${txtrst}" | center + ;; + + * ) + echo "${txtred}File does not appear to use a valid compression method (gzip, bzip2, or compress). Please decompress manually.${txtrst}" | centerwide + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +11 ) + clear && echo "" && echo "Are you sure you want to return to the main menu? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read exitays + case $exitays in + y | Y ) + clear && exit + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + esac +;; + +12 ) + clear && echo "" && echo "Are you sure you want to shut down? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read shutdownays + case $shutdownays in + y | Y ) + clear && shutdown -h now + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +* ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read +;; + +esac + +done +pause +} +# Purpose - Get input via the keyboard and make a decision using case..esac +local c +read -p "Enter your choice [ 1 -12 ] " c +case $c in +1) os_info ;; +2) host_info ;; +3) net_info ;; +4) user_info "who" ;; +5) user_info "last" ;; +6) mem_info ;; +7) ip_info ;; +8) disk_info ;; +9) proc_info ;; +10) user_infos ;; +11) file_info ;; +12) echo "Bye!"; exit 0 ;; +*) +echo "Please select between 1 to 12 choice only." +pause +esac +} + +# ignore CTRL+C, CTRL+Z and quit singles using the trap +trap '' SIGINT SIGQUIT SIGTSTP + +# main logic +while true +do +clear +show_menu # display memu +read_input # wait for user input +done diff --git a/SysInfoProject/scrtips/menu.sh b/SysInfoProject/scrtips/menu.sh new file mode 100644 index 0000000..a3f3cd3 --- /dev/null +++ b/SysInfoProject/scrtips/menu.sh @@ -0,0 +1,648 @@ +function show_menu(){ +date +echo "---------------------------" +echo " Main Menu" +echo "---------------------------" +echo "1. Operating system info" +echo "2. Hostname and dns info" +echo "3. Network info" +echo "4. Who is online" +echo "5. Last logged in users" +echo "6. Free and used memory info" +echo "7. Get my ip address" +echo "8. My Disk Usage" +echo "9. Process Usage" +echo "10. Users Operations" +echo "11. File Operations" +echo "12. Exit" +} + +# Purpose - Display header message +# $1 - message +local h="$@" +echo "---------------------------------------------------------------" +echo " ${h}" +echo "---------------------------------------------------------------" +} + +# Purpose - Get info about your operating system +write_header " System information " +echo "Operating system : $(uname)" +[ -x $LSB ] && $LSB -a || echo "$LSB command is not insalled (set \$LSB variable)" +#pause "Press [Enter] key to continue..." +pause +} + +# Purpose - Get info about host such as dns, IP, and hostname +local dnsips=$(sed -e '/^$/d' /etc/resolv.conf | awk '{if (tolower($1)=="nameserver") print $2}') +write_header " Hostname and DNS information " +echo "Hostname : $(hostname -s)" +echo "DNS domain : $(hostname -d)" +echo "Fully qualified domain name : $(hostname -f)" +echo "Network address (IP) : $(hostname -i)" +echo "DNS name servers (DNS IP) : ${dnsips}" +pause +} + +# Purpose - Network inferface and routing info +devices=$(ss -i | cut -d" " -f1 | egrep -v "^Kernel|Iface|lo") +write_header " Network information " +echo "Total network interfaces found : $(wc -w <<<${devices})" + +echo "*** IP Addresses Information ***" +ip -4 address show + +echo "***********************" +echo "*** Network routing ***" +echo "***********************" +ss -r + +echo "**************************************" +echo "*** Interface traffic information ***" +echo "**************************************" +ss -i + +pause +} + +# Purpose - Display a list of users currently logged on +# display a list of receltly loggged in users +local cmd="$1" +case "$cmd" in +who) write_header " Who is online "; who -H; pause ;; +last) write_header " List of last logged in users "; last ; pause ;; +esac +} + +# Purpose - Display used and free memory info +write_header " Free and used memory " +free -m + +echo "*********************************" +echo "*** Virtual memory statistics ***" +echo "*********************************" +vmstat +echo "***********************************" +echo "*** Top 5 memory eating process ***" +echo "***********************************" +ps auxf | sort -nr -k 4 | head -5 +pause +} + +# Purpose - Get Public IP address form your ISP +cmd='curl -s' +write_header " Public IP information " +ipservice=checkip.dyndns.org +pipecmd=(sed -e 's/.*Current IP Address: //' -e 's/<.*$//') #using brackets to use it as an array and avoid need of scaping +$cmd "$ipservice" | "${pipecmd[@]}" +pause +} + +# purpose - Get Disk Usage Information +usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1) + partition=$(echo $output | awk '{print $2}') +write_header " Disk Usage Info" +if [ "$EXCLUDE_LIST" != "" ] ; then + df -H | grep -vE "^Filesystem|tmpfs|cdrom|${EXCLUDE_LIST}" | awk '{print $5 " " $6}' +else + df -H | grep -vE "^Filesystem|tmpfs|cdrom" | awk '{print $5 " " $6}' +fi +pause +} +#Purpose of Process Usage Information + +write_header " Process Usage Info" + + + +s %s\n" ' ' "$line" + done +} + +s %s\n" ' ' "$line" + done +} + +while : +do + +clear + +echo "" +echo "" +echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide +echo "" +echo "1. Show all processes" | center +echo "2. Kill a process" | center +echo "3. Bring up top" | center +echo "4. ${txtpur}Return to Main Menu${txtrst}" | center +echo "5. ${txtred}Shut down${txtrst}" | center +echo "" + +read processmenuchoice +case $processmenuchoice in + +1 ) + clear && echo "" && echo "${txtcyn}(press ENTER or use arrow keys to scroll list, press Q to return to menu)${txtrst}" | centerwide && read + ps -ef | less +;; + +2 ) + clear && echo "" && echo "Please enter the PID of the process you would like to kill:" | centerwide + read pidtokill + kill -2 $pidtokill && echo "${txtgrn}Process terminated successfully.${txtrst}" | center || echo "${txtred}Process failed to terminate. Please check the PID and try again.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +3 ) + top +;; + +4 ) + clear && echo "" && echo "Are you sure you want to return to the main menu? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read exitays + case $exitays in + y | Y ) + clear && exit + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + esac +;; + +5 ) + clear && echo "" && echo "Are you sure you want to shut down? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read shutdownays + case $shutdownays in + y | Y ) + clear && shutdown -h now + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +* ) + clear && echo "" && echo "${txtred}Please make a valid selection." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read +;; +esac + +done +pause +} + +#Purpose - For getting User operation and infrmations + +write_header "User Operations" + + + + +s %s\n" ' ' "$line" + done +} + +s %s\n" ' ' "$line" + done +} + +while : +do + +clear + +echo "" +echo "" +echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide +echo "" +echo "1. Create a user" | center +echo "2. Change the group for a user" | center +echo "3. Create a group" | center +echo "4. Delete a user" | center +echo "5. Change a password" | center +echo "6. ${txtpur}Return to Main Menu${txtrst}" | center +echo "7. ${txtred}Shut down${txtrst}" | center +echo "" + +read usermenuchoice +case $usermenuchoice in + +1 ) + clear && echo "" && echo "Please enter the new username below: ${txtcyn}(NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read newusername + echo "" && echo "Please enter a group for the new user: ${txtcyn}(STILL NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read newusergroup + echo "" && echo "What is the new user's full name? ${txtcyn}(YOU CAN USE SPACES HERE IF YOU WANT!)${txtrst}" | centerwide && echo "" + read newuserfullname + echo "" && echo "" + groupadd $newusergroup + useradd -g $newusergroup -c "$newuserfullname" $newusername && echo "${txtgrn}New user $newusername created successfully.${txtrst}" | center || echo "${txtred}Could not create new user.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +2 ) + clear && echo "" && echo "Which user needs to be in a different group? ${txtcyn}(USER MUST EXIST!)${txtrst}" | centerwide && echo "" + read usermoduser + echo "" && echo "What should be the new group for this user? ${txtcyn}(NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read usermodgroup + echo "" && echo "" + groupadd $usermodgroup + usermod -g $usermodgroup $usermoduser && echo "${txtgrn}User $usermoduser added to group $usermodgroup successfully.${txtrst}" | center || echo "${txtred}Could not add user to group. Please check if user exists.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +3 ) + clear && echo "" && echo "Please enter a name for the new group below: ${txtcyn}(NO SPACES OR SPECIAL CHARACTERS!)${txtrst}" | centerwide && echo "" + read newgroup + echo "" && echo "" + groupadd $newgroup && echo "${txtgrn}Group $newgroup created successfully.${txtrst}" | center || echo "${txtred}Failed to create group. Please check if group already exists.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +4 ) + clear && echo "" && echo "Please enter the username to be deleted below: ${txtcyn}(THIS CANNOT BE UNDONE!)${txtrst}" | centerwide && echo "" + read deletethisuser + echo "" && echo "${txtred}ARE YOU ABSOLUTELY SURE YOU WANT TO DELETE THIS USER? SERIOUSLY, THIS CANNOT BE UNDONE! ${txtcyn}y/n${txtrst}" | centerwide + read deleteuserays + echo "" && echo "" + case $deleteuserays in + y | Y ) + if id "$deletethisuser" &>/dev/null; then + userdel "$deletethisuser" + log_action "Deleted user $deletethisuser" +else + echo "User $deletethisuser does not exist." +fi && echo "${txtgrn}User $deletethisuser deleted successfully." | center || echo "${txtred}Failed to delete user. Please check username and try again.${txtrst}" | centerwide + ;; + n | N ) + echo "Okay. Nevermind then." | center + ;; + * ) + echo "${txtred}Please make a valid selection.${txtrst}" | center + ;; + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +5 ) + clear && echo "" && echo "Which user's password should be changed?" | centerwide + read passuser + echo "" + passwd $passuser && echo "${txtgrn}Password for $passuser changed successfully.${txtrst}" | center || echo "${txtred}Failed to change password.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center + read +;; + +6 ) + clear && echo "" && echo "Are you sure you want to return to the main menu? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read exitays + case $exitays in + y | Y ) + clear && exit + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +7 ) + clear && echo "" && echo "Are you sure you want to shut down? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read shutdownays + case $shutdownays in + y | Y ) + clear && shutdown -h now + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +* ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read +;; + +esac + +done +pause +} + +#Purpose - For File Opertios +write_header "File OPerations" + + + +s %s\n" ' ' "$line" + done +} + +s %s\n" ' ' "$line" + done +} + +while : +do + +clear + +echo "" +echo "" +echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide +echo "" +echo "1. Create a file" | center +echo "2. Delete a file" | center +echo "3. Create a directory" | center +echo "4. Delete a directory" | center +echo "5. Create a symbolic link" | center +echo "6. Change ownership of a file" | center +echo "7. Change permissions on a file" | center +echo "8. Modify text within a file" | center +echo "9. Compress a file" | center +echo "10. Decompress a file" | center +echo "11. ${txtpur}Return to main menu${txtrst}" | center +echo "12. ${txtred}Shut down${txtrst}" | center +echo "" + +read mainmenuchoice +case $mainmenuchoice in + +1 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center + echo "" && echo "Please enter the ${txtcyn}full path${txtrst} and filename for the new file:" | centerwide && echo "" + echo "${txtcyn}(if file exists, it will be touched)${txtrst}" | center && echo "" + read touchfile + echo "" && echo "" + touch $touchfile && echo "${txtgrn}File $touchfile touched successfully.${txtrst}" | centerwide || echo "${txtred}Touch failed. How did you even do that?${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +2 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center && echo "" && ls && echo "" + echo "Please enter the ${txtcyn}full path${txtrst} and filename for the file to be deleted:" | centerwide && echo "" + read rmfile + echo "" && echo "" + if [[ -f "$rmfile" ]]; then + rm -i "$rmfile" + log_action "Deleted file $rmfile" +else + echo "File $rmfile does not exist." +fi && echo "${txtgrn}File removed successfully.${txtrst}" | center || echo "${txtred}File removal failed.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +3 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center && echo "" && ls && echo "" + echo "Please enter the ${txtcyn}full path${txtrst} for the directory to be created:" | centerwide && echo "" + read mkdirdir + echo "" && echo "" + mkdir $mkdirdir && echo "${txtgrn}Directory $mkdirdir created successfully.${txtrst}" | centerwide || echo "${txtred}Failed to create directory.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +4 ) + clear && echo "" && echo "Current working directory:" | center && pwd | center && echo "" && ls && echo "" + echo "Please enter the ${txtcyn}full path${txtrst} for the directory to be removed: ${txtcyn}(MUST BE EMPTY!)${txtrst}" | centerwide && echo "" + read rmdirdir + echo "" && echo "" + rmdir $rmdirdir && echo "${txtgrn}Directory $rmdirdir removed successfully.${txtrst}" | centerwide || echo "${txtred}Failed to remove directory. Please ensure directory is empty.${txtrst}" | centerwide + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +5 ) + clear && echo "" && echo "Please enter the input file for the symbolic link: ${txtcyn}(FULL PATH!)${txtrst}" | centerwide && echo "" + read symlinfile + echo "" && echo "Please enter the output file for the symbolic link: ${txtcyn}(SERIOUSLY, FULL PATH!)${txtrst}" | centerwide && echo "" + read symloutfile + echo "" && echo "" + +if [[ -e "$symlinfile" ]]; then + ln -s "$symlinfile" "$symloutfile" + if [[ -L "$symloutfile" ]]; then + echo "Symbolic link created successfully at $symloutfile" + log_action "Created symbolic link from $symlinfile to $symloutfile" + else + echo "Failed to create symbolic link." + fi +else + echo "Input file $symlinfile does not exist." +fi + cat $symloutfile && clear && echo "" && echo "${txtgrn}Symbolic link created successfully at $symloutfile${txtrst}" | centerwide || echo "${txtred}Failed to create symbolic link. Please check paths and filenames and try again.${txtrst}" | centerwide && rm -f $symloutfile + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +6 ) + clear && echo "" && echo "Which file's ownership should be changed? ${txtcyn}(MUST EXIST, USE FULL PATH!)${txtrst}" | centerwide && echo "" + read chownfile + echo "" && echo "Please enter the username for the new owner of $chownfile: ${txtcyn}(USER MUST EXIST)${txtrst}" | centerwide && echo "" + read chownuser + echo "" && echo "Please enter the new group for $chownfile: ${txtcyn}(GROUP MUST EXIST)${txtrst}" | centerwide && echo "" + read chowngroup + echo "" && echo "" + chown $chownuser.$chowngroup $chownfile && echo "${txtgrn}Ownership of $chownfile changed successfully.${txtrst}" | centerwide || echo "${txtred}Failed to change ownership. Please check if user, group and file exist.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +7 ) + clear && echo "" && echo "Which file's permissions should be changed? ${txtcyn}(MUST EXIST, USE FULL PATH!)${txtrst}" | centerwide && echo "" + read chmodfile + echo "" && echo "Please enter the three-digit numeric string for the permissions you would like to set:" | centerwide + echo "" + echo "${txtcyn}( format is [owner][group][all] | ex: ${txtrst}777${txtcyn} for full control for everyone )${txtrst}" | centerwide + echo "" + echo "${txtcyn}4 = read${txtrst}" | center + echo "${txtcyn}2 = write${txtrst}" | center + echo "${txtcyn}1 = execute${txtrst}" | center + echo "" + read chmodnum + echo "" && echo "" + chmod $chmodnum $chmodfile && echo "${txtgrn}Permissions for $chmodfile changed successfully.${txtrst}" | centerwide || echo "${txtred}Failed to set permissions.${txtrst}" | center + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +8 ) + clear && echo "" && echo "Please enter the full path and filename for the file you wish to edit:" | centerwide && echo "" + read editfile + echo "Which program would you like to use to edit this file?" | centerwide && echo "" + echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide + echo "1. vim" | center + echo "2. nano" | center + echo "3. mcedit" | center + echo "4. emacs" | center + echo "5. pico" | center + echo "" + read editapp + echo "" + case $editapp in + 1 ) + vim $editfile || echo "${txtred}Failed to open vim. Please check if it is installed.${txtrst}" | centerwide + ;; + + 2 ) + nano $editfile || echo "${txtred}Failed to open nano. Please check if it is installed.${txtrst}" | centerwide + ;; + + 3 ) + mcedit $editfile || echo "${txtred}Failed to open mcedit. Please check if it is installed.${txtrst}" | centerwide + ;; + + 4 ) + emacs $editfile || echo "${txtred}Failed to open emacs. Please check if it is installed.${txtrst}" | centerwide + ;; + + 5 ) + pico $editfile || echo "${txtred}Failed to open pico. Please check if it is installed.${txtrst}" | centerwide + ;; + + * ) + echo "${txtred}Please make a valid selection.${txtrst}" | center + ;; + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +9 ) + clear && echo "" && echo "Please enter the ${txtcyn}full path${txtrst} and filename for the file you wish to compress:" | centerwide && echo "" + read pressfile + echo "" && echo "Which method of compression would you like to use?" | centerwide && echo "" + echo "${txtcyn}(please enter the number of your selection below)${txtrst}" | centerwide + echo "" + echo "1. gzip" | center + echo "2. bzip2" | center + echo "3. compress" | center + echo "" + read pressmethod + echo "" + case $pressmethod in + 1 ) + gzip $pressfile && echo "${txtgrn}File compressed successfully.${txtrst}" | center || echo "${txtred}File failed to compress.${txtrst}" | center + ;; + + 2 ) + bzip2 $pressfile && echo "${txtgrn}File compressed successfully.${txtrst}" | center || echo "${txtred}File failed to compress.${txtrst}" | center + ;; + + 3 ) + compress $pressfile && echo "${txtgrn}File compressed successfully.${txtrst}" | center || echo "${txtred}File failed to compress.${txtrst}" | center + ;; + + * ) + echo "${txtred}Please make a valid selection.${txtrst}" | center + ;; + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +10 ) + clear && echo "" && echo "Please enter the ${txtcyn}full path${txtrst} and filename for the file you wish to decompress:" | centerwide && echo "" + read depressfile + case $depressfile in + *.gz | *.GZ ) + gunzip $depressfiles && echo "${txtgrn}File decompressed successfully.${txtrst}" | center || echo "${txtred}File failed to decompress.${txtrst}" | center + ;; + + *.bz2 | *.BZ2 ) + bunzip2 $depressfile && echo "${txtgrn}File decompressed successfully.${txtrst}" | center || echo "${txtred}File failed to decompress.${txtrst}" | center + ;; + + *.z | *.Z ) + uncompress $depressfile && echo "${txtgrn}File decompressed successfully.${txtrst}" | center || echo "${txtred}File failed to decompress.${txtrst}" | center + ;; + + * ) + echo "${txtred}File does not appear to use a valid compression method (gzip, bzip2, or compress). Please decompress manually.${txtrst}" | centerwide + esac + echo "" && echo "${txtcyn}(press ENTER to continue)${txtrst}" | center && read +;; + +11 ) + clear && echo "" && echo "Are you sure you want to return to the main menu? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read exitays + case $exitays in + y | Y ) + clear && exit + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + esac +;; + +12 ) + clear && echo "" && echo "Are you sure you want to shut down? ${txtcyn}y/n${txtrst}" | centerwide && echo "" + read shutdownays + case $shutdownays in + y | Y ) + clear && shutdown -h now + ;; + n | N ) + clear && echo "" && echo "Okay. Nevermind then." | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + * ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read + ;; + esac +;; + +* ) + clear && echo "" && echo "${txtred}Please make a valid selection.${txtrst}" | center && echo "" && echo "${txtcyn}(Press ENTER to continue.)${txtrst}" | center && read +;; + +esac + +done +pause +} +# Purpose - Get input via the keyboard and make a decision using case..esac +function read_input(){ +local c +read -p "Enter your choice [ 1 -12 ] " c +case $c in +1) os_info ;; +2) host_info ;; +3) net_info ;; +4) user_info "who" ;; +5) user_info "last" ;; +6) mem_info ;; +7) ip_info ;; +8) disk_info ;; +9) proc_info ;; +10) user_infos ;; +11) file_info ;; +12) echo "Bye!"; exit 0 ;; +*) +echo "Please select between 1 to 12 choice only." +pause +esac +} + +# ignore CTRL+C, CTRL+Z and quit singles using the trap +trap '' SIGINT SIGQUIT SIGTSTP + +# main logic +while true +do +clear +show_menu # display memu +read_input # wait for user input +done diff --git a/tar_matching_dirs.sh b/tar_matching_dirs.sh new file mode 100644 index 0000000..79d82cb --- /dev/null +++ b/tar_matching_dirs.sh @@ -0,0 +1,74 @@ +#!/bin/bash +#Arguments. +#./tar_matching_dirs.sh /path/to/base "ALL|#" /path/to/target + +# Arguments +BASE_DIR="${1:-.}" +LIMIT="${2:-0}" +TARGET_DIR="${3:-.}" + +# Create target directory if it doesn't exist +mkdir -p "$TARGET_DIR" + +# Clean up old .tar.gz files in the target directory +echo "Cleaning up old archives in $TARGET_DIR..." +find "$TARGET_DIR" -maxdepth 1 -type f -name '*.tar.gz' -exec rm -f {} \; + +# Log file setup +LOG_FILE="archive_log_$(date +%Y%m%d_%H%M%S).log" +LOG_ARCHIVE="${LOG_FILE%.log}.tar.gz" + +# Get server info +HOSTNAME=$(hostname) +IP_ADDRESS=$(hostname -I | awk '{print $1}') + +# Start logging with server info +{ + echo "Archiving started at $(date)" + echo "Server Hostname: $HOSTNAME" + echo "Server IP Address: $IP_ADDRESS" + echo "----------------------------------------" +} > "$LOG_FILE" + +# Check if base directory exists +if [ ! -d "$BASE_DIR" ]; then + echo "Error: Base directory '$BASE_DIR' does not exist." | tee -a "$LOG_FILE" + exit 1 +fi + +# Counter for limiting archives +count=0 + +# Find and process matching directories (only one level deep) +find "$BASE_DIR" -mindepth 2 -maxdepth 2 -type d -regextype posix-extended -regex '.*/[0-9]{6}-[0-9]{6}' | while read -r dir; do + # Check limit unless it's "ALL" + if [[ "$LIMIT" != "ALL" && "$LIMIT" -gt 0 && "$count" -ge "$LIMIT" ]]; then + break + fi + + dir_name=$(basename "$dir") + parent_dir=$(dirname "$dir") + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + tar_file="${TARGET_DIR}/${dir_name}.tar.gz" + + echo "[$timestamp] Archiving: $dir" | tee -a "$LOG_FILE" + + if tar -czf "$tar_file" -C "$parent_dir" "$dir_name" 2>>"$LOG_FILE"; then + echo "[$timestamp] Success: Created $tar_file" | tee -a "$LOG_FILE" + else + echo "[$timestamp] Error: Failed to archive $dir. See details below:" | tee -a "$LOG_FILE" + tail -n 5 "$LOG_FILE" | tee -a "$LOG_FILE" + fi + + count=$((count + 1)) +done + +echo "Archiving completed at $(date)" >> "$LOG_FILE" + +# Package the log file and move it to target directory +if tar -czf "$LOG_ARCHIVE" "$LOG_FILE"; then + mv "$LOG_ARCHIVE" "$TARGET_DIR/" + echo "Log file archived as ${TARGET_DIR}/$(basename "$LOG_ARCHIVE")" +else + echo "Failed to archive the log file." +fi