From ba2a512bc0547924127d28ff3ecd396ed9a5fd09 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 29 Aug 2025 14:16:23 -0700 Subject: [PATCH 01/45] Create tar_matching_dirs.sh --- tar_matching_dirs.sh | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tar_matching_dirs.sh 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 From 73d3f7c4106445ae4caf1c2a54eb9ebc0b95d159 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 29 Aug 2025 15:25:07 -0700 Subject: [PATCH 02/45] Create menu.sh --- SysInfoProject/scrtips/menu.sh | 648 +++++++++++++++++++++++++++++++++ 1 file changed, 648 insertions(+) create mode 100644 SysInfoProject/scrtips/menu.sh 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 From 726e822a13321ccf3d76b0a7a9ccd9e9ed2ff57c Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 29 Aug 2025 15:25:39 -0700 Subject: [PATCH 03/45] Create main.sh --- SysInfoProject/scrtips/main.sh | 629 +++++++++++++++++++++++++++++++++ 1 file changed, 629 insertions(+) create mode 100644 SysInfoProject/scrtips/main.sh 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 From 86ef28a49226ac871cc682cb50de5e41fe9ac883 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 29 Aug 2025 15:26:19 -0700 Subject: [PATCH 04/45] Create functions.sh --- SysInfoProject/scrtips/functions.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 SysInfoProject/scrtips/functions.sh 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(){ From 2adba930c8016dd9820c599c73dc60dff3945740 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 29 Aug 2025 15:26:47 -0700 Subject: [PATCH 05/45] Add files via upload --- SysInfoProject/README.md | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 SysInfoProject/README.md 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. From 0cec2f3c221f7e1d5e1d2415bc161d0259aa55c1 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 10 Sep 2025 16:06:34 -0700 Subject: [PATCH 06/45] Create nfs_export_setup.sh This script includes: Argument support for directory and client IP. Directory existence check with user confirmation. Backup of /etc/exports before changes. Error handling and rollback option. Export summary display. --- SysInfoProject/NFS/nfs_export_setup.sh | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 SysInfoProject/NFS/nfs_export_setup.sh 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 From ed982bf04d736fc795ebed233b29f49a842d8623 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 10 Sep 2025 16:08:10 -0700 Subject: [PATCH 07/45] Create README.md The README.md includes: Features Requirements Usage instructions Example command Rollback behavior License note --- SysInfoProject/NFS/README.md | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 SysInfoProject/NFS/README.md 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. From 8e1b05d901a3bf07aa501df269c5627f1aa49b08 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 10 Sep 2025 16:20:12 -0700 Subject: [PATCH 08/45] Create nfs_client_setup.sh This script: Accepts server IP and mount directory as arguments Validates and optionally creates the mount point Mounts the NFS share Displays a summary Prompts to make the mount permanent via /etc/fstab --- .../NFS/NFS_Client/nfs_client_setup.sh | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh 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..f3c9aad --- /dev/null +++ b/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# NFS Client Setup Script with Summary and fstab Option + +# Usage check +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +SERVER_IP="$1" +MOUNT_DIR="$2" +REMOTE_DIR="/srv/nfs/shared" + +# 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 From 1d24004517754aaf822eb13b7d2f4e51a38e48dd Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 10 Sep 2025 16:21:50 -0700 Subject: [PATCH 09/45] Create README.md The README.md includes: Features Requirements Usage instructions Example command Explanation of the /etc/fstab option --- SysInfoProject/NFS/NFS_Client/README.md | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 SysInfoProject/NFS/NFS_Client/README.md diff --git a/SysInfoProject/NFS/NFS_Client/README.md b/SysInfoProject/NFS/NFS_Client/README.md new file mode 100644 index 0000000..334bf72 --- /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 and mount directory 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 +``` + +## 📁 Output +- Creates the mount point if it doesn't exist +- Mounts the NFS share from `/srv/nfs/shared` on the server +- 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. From a323fe790945a16d90df260411c54265dd146132 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 10 Sep 2025 16:30:25 -0700 Subject: [PATCH 10/45] Update nfs_client_setup.sh The new third argument: REMOTE_DIR Updated usage and example Clear explanation of the /etc/fstab option --- SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh b/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh index f3c9aad..1488b04 100644 --- a/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh +++ b/SysInfoProject/NFS/NFS_Client/nfs_client_setup.sh @@ -1,15 +1,15 @@ #!/bin/bash -# NFS Client Setup Script with Summary and fstab Option +# NFS Client Setup Script with REMOTE_DIR Argument # Usage check -if [ "$#" -ne 2 ]; then - echo "Usage: $0 " +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " exit 1 fi SERVER_IP="$1" MOUNT_DIR="$2" -REMOTE_DIR="/srv/nfs/shared" +REMOTE_DIR="$3" # Check if mount point exists if [ -d "$MOUNT_DIR" ]; then @@ -20,7 +20,7 @@ if [ -d "$MOUNT_DIR" ]; then exit 1 fi else - echo "📁 Creating mount point $MOUNT_DIR..." + echo " Creating mount point $MOUNT_DIR..." if ! mkdir -p "$MOUNT_DIR"; then echo "❌ Failed to create mount point." exit 1 @@ -28,7 +28,7 @@ else fi # Mount the NFS share -echo "🔗 Mounting $SERVER_IP:$REMOTE_DIR to $MOUNT_DIR..." +echo " Mounting $SERVER_IP:$REMOTE_DIR to $MOUNT_DIR..." if mount | grep -q "$MOUNT_DIR"; then echo "✅ Already mounted." else From 539643c4261f25aa4a74e94da3059f488c1be596 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 10 Sep 2025 16:31:07 -0700 Subject: [PATCH 11/45] Update README.md UPdate --- SysInfoProject/NFS/NFS_Client/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SysInfoProject/NFS/NFS_Client/README.md b/SysInfoProject/NFS/NFS_Client/README.md index 334bf72..18cae8c 100644 --- a/SysInfoProject/NFS/NFS_Client/README.md +++ b/SysInfoProject/NFS/NFS_Client/README.md @@ -3,7 +3,7 @@ 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 and mount directory as arguments +- 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 @@ -15,17 +15,17 @@ This script automates the process of mounting an NFS (Network File System) share ## 🚀 Usage ```bash -sudo ./nfs_client_setup.sh +sudo ./nfs_client_setup.sh ``` ### Example ```bash -sudo ./nfs_client_setup.sh 192.168.1.10 /mnt/nfs/shared +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 `/srv/nfs/shared` on the server +- Mounts the NFS share from the specified remote directory - Displays the current mount status ## 📌 fstab Option From 4e7bc7560f3b61d71ffa5df758cec08da3359d5c Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 30 Sep 2025 10:02:11 -0700 Subject: [PATCH 12/45] Create setup_x11_forwarding.sh Creation of Script X11. --- SysInfoProject/X-11/setup_x11_forwarding.sh | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 SysInfoProject/X-11/setup_x11_forwarding.sh diff --git a/SysInfoProject/X-11/setup_x11_forwarding.sh b/SysInfoProject/X-11/setup_x11_forwarding.sh new file mode 100644 index 0000000..0d0fac9 --- /dev/null +++ b/SysInfoProject/X-11/setup_x11_forwarding.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +TARGET_USER=\"$1\" + +if [ -z \"$TARGET_USER\" ]; then + echo \"Error: No target user specified.\" + echo \"Usage: $0 \" + exit 1 +fi + +DISPLAY_VAL=$(env | grep DISPLAY | cut -d= -f2) +if [ -z \"$DISPLAY_VAL\" ]; then + echo \"Error: DISPLAY environment variable is not set.\" + exit 2 +fi + +COOKIE=$(xauth list | grep \"unix$(echo $DISPLAY_VAL | cut -c10-12)\") +if [ -z \"$COOKIE\" ]; then + echo \"Error: No xauth cookie found for DISPLAY=$DISPLAY_VAL\" + exit 3 +fi + +echo \"$COOKIE\" > /tmp/z_xauth +if [ $? -ne 0 ]; then + echo \"Error: Failed to write xauth cookie to /tmp/z_xauth\" + exit 4 +fi + +sudo -u \"$TARGET_USER\" bash < /dev/null; then + echo \"Error: xauth not found for user $TARGET_USER\" + exit 5 + fi + + xauth add $COOKIE + echo \"xauth list for $TARGET_USER:\" + xauth list +EOF + +rm -f /tmp/z_xauth + +echo \"✅ X11 forwarding setup complete for user '$TARGET_USER'.\" From adba2603c3264ec6ec73c1a97368c6c04288b12e Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 19:06:36 -0700 Subject: [PATCH 13/45] Delete SysInfoProject/X-11/setup_x11_forwarding.sh Remove failure scrtip new scrtip will be created --- SysInfoProject/X-11/setup_x11_forwarding.sh | 42 --------------------- 1 file changed, 42 deletions(-) delete mode 100644 SysInfoProject/X-11/setup_x11_forwarding.sh diff --git a/SysInfoProject/X-11/setup_x11_forwarding.sh b/SysInfoProject/X-11/setup_x11_forwarding.sh deleted file mode 100644 index 0d0fac9..0000000 --- a/SysInfoProject/X-11/setup_x11_forwarding.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -TARGET_USER=\"$1\" - -if [ -z \"$TARGET_USER\" ]; then - echo \"Error: No target user specified.\" - echo \"Usage: $0 \" - exit 1 -fi - -DISPLAY_VAL=$(env | grep DISPLAY | cut -d= -f2) -if [ -z \"$DISPLAY_VAL\" ]; then - echo \"Error: DISPLAY environment variable is not set.\" - exit 2 -fi - -COOKIE=$(xauth list | grep \"unix$(echo $DISPLAY_VAL | cut -c10-12)\") -if [ -z \"$COOKIE\" ]; then - echo \"Error: No xauth cookie found for DISPLAY=$DISPLAY_VAL\" - exit 3 -fi - -echo \"$COOKIE\" > /tmp/z_xauth -if [ $? -ne 0 ]; then - echo \"Error: Failed to write xauth cookie to /tmp/z_xauth\" - exit 4 -fi - -sudo -u \"$TARGET_USER\" bash < /dev/null; then - echo \"Error: xauth not found for user $TARGET_USER\" - exit 5 - fi - - xauth add $COOKIE - echo \"xauth list for $TARGET_USER:\" - xauth list -EOF - -rm -f /tmp/z_xauth - -echo \"✅ X11 forwarding setup complete for user '$TARGET_USER'.\" From 0065809b203365f5fab8ddaccceac475abee8f74 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 19:07:41 -0700 Subject: [PATCH 14/45] Create setup_x11_forwarding.sh New Scrtip --- SysInfoProject/X11/setup_x11_forwarding.sh | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 SysInfoProject/X11/setup_x11_forwarding.sh diff --git a/SysInfoProject/X11/setup_x11_forwarding.sh b/SysInfoProject/X11/setup_x11_forwarding.sh new file mode 100644 index 0000000..520fcb2 --- /dev/null +++ b/SysInfoProject/X11/setup_x11_forwarding.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +TARGET_USER="$1" + +if [ -z "$TARGET_USER" ]; then + echo "❌ Error: No target user specified." + echo "Usage: $0 " + exit 1 +fi + +# Obtener el valor de DISPLAY, usar :0 como valor por defecto si no está definido +DISPLAY_VAL="${DISPLAY:-:0}" + +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 + From baa34e66439181b088ea2ccfa121028f10b35422 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 19:11:25 -0700 Subject: [PATCH 15/45] Update setup_x11_forwarding.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Perfecto, Manuel. Aquí tienes el script actualizado para que use :10 como valor por defecto si la variable DISPLAY no está definida: --- SysInfoProject/X11/setup_x11_forwarding.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SysInfoProject/X11/setup_x11_forwarding.sh b/SysInfoProject/X11/setup_x11_forwarding.sh index 520fcb2..9bfde02 100644 --- a/SysInfoProject/X11/setup_x11_forwarding.sh +++ b/SysInfoProject/X11/setup_x11_forwarding.sh @@ -8,8 +8,8 @@ if [ -z "$TARGET_USER" ]; then exit 1 fi -# Obtener el valor de DISPLAY, usar :0 como valor por defecto si no está definido -DISPLAY_VAL="${DISPLAY:-:0}" +# 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." @@ -65,3 +65,4 @@ fi # Limpiar archivo temporal rm -f /tmp/z_xauth +echo "✅ X11 forwarding setup complete for user '$TARGET_USER'." From ba0d1f6e6f17fd5adafe12a9cbaa3705c449e4cb Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:19:07 -0700 Subject: [PATCH 16/45] Create top-swap.sh Create script for swap check --- SysInfoProject/mem_monitor/top-swap.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 SysInfoProject/mem_monitor/top-swap.sh diff --git a/SysInfoProject/mem_monitor/top-swap.sh b/SysInfoProject/mem_monitor/top-swap.sh new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/SysInfoProject/mem_monitor/top-swap.sh @@ -0,0 +1 @@ + From 811884fba1512f62d143501a1b78e1b042b95d67 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:19:38 -0700 Subject: [PATCH 17/45] Update top-swap.sh SWAP check --- SysInfoProject/mem_monitor/top-swap.sh | 212 +++++++++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/SysInfoProject/mem_monitor/top-swap.sh b/SysInfoProject/mem_monitor/top-swap.sh index 8b13789..5c340d4 100644 --- a/SysInfoProject/mem_monitor/top-swap.sh +++ b/SysInfoProject/mem_monitor/top-swap.sh @@ -1 +1,213 @@ +#!/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] +# NEW: --show-user — include a User column (pretty & TSV) +# +# Examples: +# ./top-swap.sh +# ./top-swap.sh -n 20 --show-user +# ./top-swap.sh --mine --show-user +# ./top-swap.sh -u postgres --tsv --show-user | column -t -s $'\t' +# sudo ./top-swap.sh -U 0 --show-user +set -euo pipefail + +TOP=10 +OUTPUT="pretty" # "pretty" or "tsv" +SHOW_ALL=0 +SHOW_USER=0 # <-- new flag + +# User filtering +ONLY_MINE=0 +USERS=() # usernames +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 + +Output columns: + Default (pretty): PID Name Swap(kB) Command + With --show-user: PID Name User Swap(kB) Command + TSV (default): PIDNameSwap_kBCmdline + TSV (+show-user): PIDNameUserSwap_kBCmdline + +Notes: + - Run with sudo to see other users' processes if /proc is restricted (e.g., hidepid) or cmdline is unreadable. + - Filtering uses the Real UID from /proc//status (Uid: line). + - Kernel threads or unreadable cmdlines are shown as [Name], similar to ps. +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 list (comma-separated unique UIDs) +declare -A UID_SET=() +if [[ "$ONLY_MINE" -eq 1 ]]; then + UID_SET["$(id -u)"]=1 +fi +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 +for uid in "${UIDS[@]}"; do + if [[ "$uid" =~ ^[0-9]+$ ]]; then + UID_SET["$uid"]=1 + else + echo "Warning: invalid UID '$uid' (skipping)" >&2 + fi +done +UID_FILTER="" +for k in "${!UID_SET[@]}"; do + UID_FILTER+="${UID_FILTER:+,}$k" +done + +# Locale-neutral sort for numbers +export LC_ALL=C + +# 1) Build list: \t\t\t (filter by UID if provided) +list_cmd=( + 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 in value + $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 +) + +# 2) Sort numerically by swap descending; optionally take top N +if [[ "$SHOW_ALL" -eq 1 ]]; then + sorted=$("${list_cmd[@]}" | sort -k1,1nr) +else + sorted=$("${list_cmd[@]}" | sort -k1,1nr | head -n "$TOP") +fi + +# If no results, exit gracefully +if [[ -z "${sorted}" ]]; 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 UID -> username (cached). Fallback to "#" if unknown. +resolve_user() { + local uid="$1" + [[ -n "$uid" ]] || { echo "-"; return; } + if [[ -n "${USER_CACHE[$uid]:-}" ]]; then + echo "${USER_CACHE[$uid]}" + return + fi + local name + name="$(getent passwd "$uid" | cut -d: -f1 || true)" + if [[ -z "$name" ]]; then + name="#$uid" + fi + USER_CACHE["$uid"]="$name" + echo "$name" +} + +# 3) Print 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 + +# 4) For each line: \t\t\t → fetch cmdline and print +while IFS=$'\t' read -r swap_kb pid uid name; do + # 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 + # Fallback for kernel threads / permission denied + if [[ -z "$cmdline" ]]; then + cmdline="[$name]" + fi + + 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 <<< "$sorted" From cbe5d1ce0d8a5c2903ff39c65e60298c4dee824b Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:44:18 -0700 Subject: [PATCH 18/45] Update top-swap.sh Fix OK --- SysInfoProject/mem_monitor/top-swap.sh | 124 ++++++++++++------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/SysInfoProject/mem_monitor/top-swap.sh b/SysInfoProject/mem_monitor/top-swap.sh index 5c340d4..98422b7 100644 --- a/SysInfoProject/mem_monitor/top-swap.sh +++ b/SysInfoProject/mem_monitor/top-swap.sh @@ -2,26 +2,25 @@ # 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] -# NEW: --show-user — include a User column (pretty & TSV) -# -# Examples: -# ./top-swap.sh -# ./top-swap.sh -n 20 --show-user -# ./top-swap.sh --mine --show-user -# ./top-swap.sh -u postgres --tsv --show-user | column -t -s $'\t' -# sudo ./top-swap.sh -U 0 --show-user +# --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 # <-- new flag +SHOW_USER=0 # User filtering ONLY_MINE=0 -USERS=() # usernames -UIDS=() # numeric UIDs +declare -a USERS=() # usernames +declare -a UIDS=() # numeric UIDs usage() { cat <<'EOF' @@ -37,16 +36,10 @@ Options: --show-user Include a User column (pretty & TSV) -h Show this help -Output columns: - Default (pretty): PID Name Swap(kB) Command - With --show-user: PID Name User Swap(kB) Command - TSV (default): PIDNameSwap_kBCmdline - TSV (+show-user): PIDNameUserSwap_kBCmdline - Notes: - - Run with sudo to see other users' processes if /proc is restricted (e.g., hidepid) or cmdline is unreadable. - - Filtering uses the Real UID from /proc//status (Uid: line). - - Kernel threads or unreadable cmdlines are shown as [Name], similar to ps. + - 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 } @@ -84,25 +77,34 @@ 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 list (comma-separated unique UIDs) +# Build the UID filter set declare -A UID_SET=() if [[ "$ONLY_MINE" -eq 1 ]]; then UID_SET["$(id -u)"]=1 fi -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 -for uid in "${UIDS[@]}"; do - if [[ "$uid" =~ ^[0-9]+$ ]]; then - UID_SET["$uid"]=1 - else - echo "Warning: invalid UID '$uid' (skipping)" >&2 - fi -done + +# 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" @@ -111,8 +113,8 @@ done # Locale-neutral sort for numbers export LC_ALL=C -# 1) Build list: \t\t\t (filter by UID if provided) -list_cmd=( +# 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) @@ -121,31 +123,31 @@ list_cmd=( 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 in value + 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 - } + 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 -) +} -# 2) Sort numerically by swap descending; optionally take top N +# Fetch and optionally limit top N if [[ "$SHOW_ALL" -eq 1 ]]; then - sorted=$("${list_cmd[@]}" | sort -k1,1nr) + mapfile -t LINES < <( gen_list | sort -k1,1nr ) else - sorted=$("${list_cmd[@]}" | sort -k1,1nr | head -n "$TOP") + mapfile -t LINES < <( gen_list | sort -k1,1nr | head -n "$TOP" ) fi # If no results, exit gracefully -if [[ -z "${sorted}" ]]; then +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 @@ -157,24 +159,19 @@ fi # Username cache for --show-user declare -A USER_CACHE=() -# Resolve UID -> username (cached). Fallback to "#" if unknown. resolve_user() { local uid="$1" - [[ -n "$uid" ]] || { echo "-"; return; } if [[ -n "${USER_CACHE[$uid]:-}" ]]; then - echo "${USER_CACHE[$uid]}" - return + echo "${USER_CACHE[$uid]}"; return fi local name name="$(getent passwd "$uid" | cut -d: -f1 || true)" - if [[ -z "$name" ]]; then - name="#$uid" - fi + [[ -n "$name" ]] || name="#$uid" USER_CACHE["$uid"]="$name" echo "$name" } -# 3) Print header +# Header if [[ "$OUTPUT" == "pretty" ]]; then if [[ "$SHOW_USER" -eq 1 ]]; then printf "%10s %-30s %-12s %12s %s\n" "PID" "Name" "User" "Swap(kB)" "Command" @@ -183,17 +180,16 @@ if [[ "$OUTPUT" == "pretty" ]]; then fi fi -# 4) For each line: \t\t\t → fetch cmdline and print -while IFS=$'\t' read -r swap_kb pid uid name; do +# 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 - # Fallback for kernel threads / permission denied - if [[ -z "$cmdline" ]]; then - cmdline="[$name]" - fi + [[ -n "$cmdline" ]] || cmdline="[$name]" if [[ "$OUTPUT" == "tsv" ]]; then if [[ "$SHOW_USER" -eq 1 ]]; then @@ -210,4 +206,4 @@ while IFS=$'\t' read -r swap_kb pid uid name; do printf "%10s %-30s %12s %s\n" "$pid" "$name" "$swap_kb" "$cmdline" fi fi -done <<< "$sorted" +done From bcbf74745c0ccda3e35f0d3768edcb415c1dcf3d Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:45:57 -0700 Subject: [PATCH 19/45] Create README.md --- SysInfoProject/mem_monitor/SWAP/README.md | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 SysInfoProject/mem_monitor/SWAP/README.md diff --git a/SysInfoProject/mem_monitor/SWAP/README.md b/SysInfoProject/mem_monitor/SWAP/README.md new file mode 100644 index 0000000..02c6950 --- /dev/null +++ b/SysInfoProject/mem_monitor/SWAP/README.md @@ -0,0 +1,28 @@ +# 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" From afe84d87ff466e9404657e86755cbbca9b97261b Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:47:28 -0700 Subject: [PATCH 20/45] Update README.md --- SysInfoProject/mem_monitor/SWAP/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/SysInfoProject/mem_monitor/SWAP/README.md b/SysInfoProject/mem_monitor/SWAP/README.md index 02c6950..8da7d98 100644 --- a/SysInfoProject/mem_monitor/SWAP/README.md +++ b/SysInfoProject/mem_monitor/SWAP/README.md @@ -26,3 +26,15 @@ 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 From 25153c448cdca3469cc36cb67eac45b9461740b6 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:47:48 -0700 Subject: [PATCH 21/45] Update README.md --- SysInfoProject/mem_monitor/SWAP/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SysInfoProject/mem_monitor/SWAP/README.md b/SysInfoProject/mem_monitor/SWAP/README.md index 8da7d98..e56e8de 100644 --- a/SysInfoProject/mem_monitor/SWAP/README.md +++ b/SysInfoProject/mem_monitor/SWAP/README.md @@ -27,13 +27,13 @@ Check your Bash version: echo "$BASH_VERSION" -##🧭 Usage +## 🧭 Usage ./top-swap.sh ./top-swap.sh --show-user ./top-swap.sh --tsv | column -t -s $'\t' -##🧪 Examples +## 🧪 Examples ./top-swap.sh -n 20 --show-user ./top-swap.sh --mine From d3825a0d884b15a28a670fc8ab63561b2d1956f6 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:55:24 -0700 Subject: [PATCH 22/45] Create top-swap.sh top-swap.sh fIx --- SysInfoProject/mem_monitor/SWAP/top-swap.sh | 209 ++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 SysInfoProject/mem_monitor/SWAP/top-swap.sh 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 From 91de4a997ff8f6616f9d3e928c8137f74ee7da01 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 22:56:16 -0700 Subject: [PATCH 23/45] Delete SysInfoProject/mem_monitor/top-swap.sh --- SysInfoProject/mem_monitor/top-swap.sh | 209 ------------------------- 1 file changed, 209 deletions(-) delete mode 100644 SysInfoProject/mem_monitor/top-swap.sh diff --git a/SysInfoProject/mem_monitor/top-swap.sh b/SysInfoProject/mem_monitor/top-swap.sh deleted file mode 100644 index 98422b7..0000000 --- a/SysInfoProject/mem_monitor/top-swap.sh +++ /dev/null @@ -1,209 +0,0 @@ -#!/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 From 560f6fcf0a415e71080af3135dc0eea7f63dac06 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 23:06:16 -0700 Subject: [PATCH 24/45] Create top-ram.sh --- SysInfoProject/mem_monitor/RAM/top-ram.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 SysInfoProject/mem_monitor/RAM/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..8b13789 --- /dev/null +++ b/SysInfoProject/mem_monitor/RAM/top-ram.sh @@ -0,0 +1 @@ + From f987f67d033a3c8d82e7b65827e23505e5ff90e0 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 23:07:08 -0700 Subject: [PATCH 25/45] Add files via upload --- SysInfoProject/mem_monitor/RAM/top-ram.sh | Bin 1 -> 4902 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/SysInfoProject/mem_monitor/RAM/top-ram.sh b/SysInfoProject/mem_monitor/RAM/top-ram.sh index 8b137891791fe96927ad78e64b0aad7bded08bdc..dd9d539c3dcf4cf456fa0be83632dc8d8fb1b060 100644 GIT binary patch literal 4902 zcmb_f|5DpX625<|j!ZV)$ zg&8fwC|6k+U-!xP*EqaQe$ny$f)^*_qw{H-KX+$%KjHV`f+oZFcsqQ*JA)SAXPvUY zPhmWdiiM)UD4!=$v5v`2GnMCGXp1h!pFGRbDkonR38i5QFT=>P!X-_oGvJHvt><@6KHW_y&cRBREc`6?m%VijuA^DInr%G7T~ zm?7|o$PoRsP3|%&;zggD2c3@kei7fq$z6Q!?a+Ad^$S$$K}W2=m^gXHIIS} z2}Pu^Iv%**gLlLC^2!pJxE_7Q!Sf)e{r%R_>2b@NFnk0X72KwbjTudShJ$<~&GOAz z<%i-yKG`LHJ87h|dRM2EcdTaCX_|*gtoyJ+AV`hB4aP@LQSL4(6!*Fw3ky~o!lwdK z3iKoJ-Ud;jv`8>=8-H>fzpE)FEQ*uZ|6OH?u*;1T;Y}2-!`vLqQFyE-iK8zKJ;*+I z1A+ofG%vDD#W{!yBDk3fA`X=3D!_%BAVkN)Ar|D#aj;e_kg5QLj1+;H!tR=zqGcjl z44v4pT1#B4LCHCv_Yy^Qwv2znmyi&-ST(}Ik0y~!ot27G3plgxEin8n$WVHM>{?rQ zs}K%>sSb#Lol{r1w@3t?*kn6B8$|#=87LkxL2PH&-b3LDmpSe3?U^;kfkzc_@T1zY z*?<&#v|&=O)Ua9RbV9*~Qja$j-%N@;8Xk`at#%8AAXt!}G3D}gddaEM;L|>gW&?$W z+XEK`XtO;1JBp0=#P|v84j0d>4i^tJgUk)ZSbRoroygL2DIAYITj6w0kY{?xo+(J( zGBQ7UWeuE|az=?z7v&C_K>^!)Ak`BorGvS(NMdDK+(zc>1#(Ei-3{p^%Yg<2F3$*1 zy;eCmu}3E3Wy|t!5kd$-e`ld?J2CgO-M3pkuG?Qrb3TSzqsvs~cu_Sx7-mG-G*epl z=)SaOQzZ|W3zy@g3$Bx!SF-k%S`? zeZPB8966*?&?QhB zp1?*L{F8p2cKyH2ww-1`{}*q<7-byiavg(H;iB~dXEt#_Mt&Jm3vsM9FS8)9vq z&yu?~b=n)#tok z96>d&$`MbOCq~xz>+H4(eY9gv0&CceV%ozf_fYAl_4#-Vt>P6U-Pxtr16W2|Td+-@ zyL5AC*HPtNuj_Dg8RGa#QRC1`%)EL(l{sLWZfl$5M2>!n`8Z#a{eym0{cj;Kx3IR& zafK)R!ETo_9C;Ieeri#Nhn0@d>c@`GgS^nqqQQL@Mhgk6miL{awhmID6GJ1Aj4^Ud z`?T*?NTzS5TKhM>b}!C6tE@7AMhH5j*ki`C9rSM7lQGwrhLS0#a`TdcYnp#qHO(Fo zY!at2npeecgt>on8+tmrnW87x8BAe1Rr7EeVl3m*=xUFrsW8^Xav9D;p3hR1t+}^g zJgrCcs=%7-z>7|F|3I;~(JX~m+EiCU)9g@~<1gPGy!&v(O$s-TB)U~HW|T!HO6C|M z8RtAE0T+#!NvAQ=Q?8WgO1R#9CwitQHFt6?#Qmzsc7KU4b2-`pV9YSMTk9jV}>r@;>)hJ;SACwBLvT*PU}@YkfIP@-du4Z zVQ@&4%ej=*u!)$E_z`6qKT6bOWSgquK(JHpcm$b^oa17CYyAZ+4FBzaSFka|aIQB% z5JXjIXdJ_vHu|TM=vi$ZrZc$|n?&<`-^_C5gzZSRdp6I~Vl$u$*QuILC3pp<&y;7> zX~qDDhQADm0a614$3&c0Du)o)1`-+wYnJ?{3ZGFVG27tkWtjexzBVxGKSKWh!Rv Date: Wed, 8 Oct 2025 23:11:26 -0700 Subject: [PATCH 26/45] Create README.md --- SysInfoProject/mem_monitor/RAM/README.md | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 SysInfoProject/mem_monitor/RAM/README.md 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 From 6e6dde43bdde1ae76946c88a658b9e875c875acc Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 Oct 2025 23:12:15 -0700 Subject: [PATCH 27/45] Update README.md From 60ad2cacced328938952f3e5e47787f83818bef4 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 29 Oct 2025 09:55:40 -0700 Subject: [PATCH 28/45] Add script to find SAP* user parameters in profiles find_sapstar_param.sh --- SysInfoProject/SAP/find_sapstar_param.sh | 61 ++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 SysInfoProject/SAP/find_sapstar_param.sh 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 From be3557c3cc439b869d13ac66748e9de6075b8d27 Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 18 Nov 2025 16:53:05 -0700 Subject: [PATCH 29/45] Add SSH setup script for user mgveliz This script sets up SSH access for the user 'mgveliz' by creating the necessary .ssh directory, configuring permissions, and appending the provided public key to authorized_keys. --- SysInfoProject/My_SSH/setup_ssh_mgveliz.sh | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 SysInfoProject/My_SSH/setup_ssh_mgveliz.sh diff --git a/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh b/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh new file mode 100644 index 0000000..848edb9 --- /dev/null +++ b/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# 1. Define Variables +TARGET_USER="mgveliz" +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_USER" "$SSH_DIR" + +echo "---------------------------------------------------" +echo "Setup complete. Permissions and ownership verified." From 4ff4949058b1db3f2ded525efdc6c1696f9ee7c2 Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 18 Nov 2025 16:55:07 -0700 Subject: [PATCH 30/45] Create README.md for SSH Key Setup Script Added a README.md file detailing the SSH key setup script for user mgveliz, including features, prerequisites, usage instructions, and script logic breakdown. --- SysInfoProject/My_SSH/README.md | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 SysInfoProject/My_SSH/README.md 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..." From 9a0c26c727535686b5cf71f324f2660c416d1063 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 20 Nov 2025 16:44:46 -0700 Subject: [PATCH 31/45] Add saprouter_manager.sh for SAProuter management This script manages the SAProuter service, allowing users to start, stop, check status, and restart the service with options for trace level control. --- SysInfoProject/SAPROUTER/saprouter_manager.sh | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 SysInfoProject/SAPROUTER/saprouter_manager.sh 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 From 1244c869da001185497f5122c4299bb4eb5475ab Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 20 Nov 2025 16:46:38 -0700 Subject: [PATCH 32/45] Create README for SAProuter management script Add README.md for SAProuter management script with features and usage instructions. --- SysInfoProject/SAPROUTER/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 SysInfoProject/SAPROUTER/README.md 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] From bba2634f7773aaa690c9ff53642401e174d130e4 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 20 Nov 2025 16:58:28 -0700 Subject: [PATCH 33/45] Add newline at end of saprouter_manager.sh Fix missing newline at end of file. From 53cc478ce21703ba879b45f8c2e9e244b8117856 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 21 Nov 2025 09:39:19 -0700 Subject: [PATCH 34/45] Change SSH directory ownership to user group --- SysInfoProject/My_SSH/setup_ssh_mgveliz.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh b/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh index 848edb9..1167965 100644 --- a/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh +++ b/SysInfoProject/My_SSH/setup_ssh_mgveliz.sh @@ -2,6 +2,7 @@ # 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" @@ -44,7 +45,7 @@ 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_USER" "$SSH_DIR" +chown -R "$TARGET_USER:$TARGET_GROUP" "$SSH_DIR" echo "---------------------------------------------------" echo "Setup complete. Permissions and ownership verified." From 975673996c348b4d663b8598ae07333f8806157d Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 21 Nov 2025 10:39:55 -0700 Subject: [PATCH 35/45] Add smart_backup.sh for backup and restore functionality This script provides a backup and restore tool with both interactive and command-line interface modes. It supports various backup formats and options for preserving directory structure. --- SysInfoProject/BACKUP_Things/smart_backup.sh | 262 +++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 SysInfoProject/BACKUP_Things/smart_backup.sh 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 From 1ddbabdb5234dea4cf0c2c156a830290cc8bf6a4 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 21 Nov 2025 10:42:22 -0700 Subject: [PATCH 36/45] Add README for Smart Backup & Restore Tool Added documentation for the Smart Backup & Restore Tool, outlining features and prerequisites. --- SysInfoProject/BACKUP_Things/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 SysInfoProject/BACKUP_Things/README.md diff --git a/SysInfoProject/BACKUP_Things/README.md b/SysInfoProject/BACKUP_Things/README.md new file mode 100644 index 0000000..c377638 --- /dev/null +++ b/SysInfoProject/BACKUP_Things/README.md @@ -0,0 +1,23 @@ +# 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 + From 312a4e5aad3657ab71e027a4f3050991da58d09d Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 21 Nov 2025 10:45:52 -0700 Subject: [PATCH 37/45] Enhance README with usage and installation details Added detailed usage instructions, installation steps, and argument reference for the Smart Backup & Restore Tool. --- SysInfoProject/BACKUP_Things/README.md | 94 +++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/SysInfoProject/BACKUP_Things/README.md b/SysInfoProject/BACKUP_Things/README.md index c377638..48f8a6c 100644 --- a/SysInfoProject/BACKUP_Things/README.md +++ b/SysInfoProject/BACKUP_Things/README.md @@ -1,3 +1,5 @@ +```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. @@ -14,10 +16,100 @@ A versatile, hybrid Bash script for Linux that handles directory backups and res The script uses standard Linux tools. For `.zip` support, ensure you have `zip` and `unzip` installed: -```bash +\`\`\`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 From 698fcb5b231219fecda8dca7c182c9610a3a8fe9 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 28 Nov 2025 10:59:20 -0700 Subject: [PATCH 38/45] Add PowerShell script to find largest files and folders --- .../Finding_files_PS1/find_files_size.PS1 | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 SysInfoProject/WIND/Finding_files_PS1/find_files_size.PS1 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 + From ce39fc1ef7a53d84b4257cf2d1787211eb3192c2 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 28 Nov 2025 10:59:56 -0700 Subject: [PATCH 39/45] Add README for PowerShell script to find largest files Added a README file for the PowerShell script that finds the largest files and folders, detailing its features and usage instructions. --- .../WIND/Finding_files_PS1/README.md | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 SysInfoProject/WIND/Finding_files_PS1/README.md 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 From 4484f3d53643fbb8f5149a74a5cc2dd17bc84a56 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 5 Dec 2025 14:02:06 -0700 Subject: [PATCH 40/45] Add sapinst_run.sh for sapinst execution with config This script runs sapinst with remote access and CRL path configuration, including error handling and hostname detection. --- SysInfoProject/SAP/SWPM/sapinst_run.sh | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 SysInfoProject/SAP/SWPM/sapinst_run.sh 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 From 8725fdf3a3a870398636b7c84cde563867e9a81e Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 12 Dec 2025 14:51:26 -0700 Subject: [PATCH 41/45] Add sapinst.ps1 script for SAP installation --- SysInfoProject/SAP/SWPM/sapinst.ps1 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 SysInfoProject/SAP/SWPM/sapinst.ps1 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" From 7e095eaecb5c55859ccfff2b3fcf5c027d618599 Mon Sep 17 00:00:00 2001 From: Manuel Date: Sat, 13 Dec 2025 11:01:44 -0700 Subject: [PATCH 42/45] Add PowerShell script to find specified processes --- SysInfoProject/WIND/FindProcess/ps_fins.ps1 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 SysInfoProject/WIND/FindProcess/ps_fins.ps1 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 +} From 3f371dfbb1ac58b0c5288f89df67d59c8d7a637c Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 23 Feb 2026 21:04:19 -0700 Subject: [PATCH 43/45] Add script to set static IP using nmcli This script configures a NetworkManager connection with a static IPv4 address using nmcli, including error handling and rollback support. --- .../Linux/set-static-ip-nmcli.sh | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 SysInfoProject/NetworkStuffs/Linux/set-static-ip-nmcli.sh 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 From 45b2dc48d90867d8aa5438178e6a6d6a9b3a15de Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 23 Feb 2026 21:05:44 -0700 Subject: [PATCH 44/45] Create README for static IPv4 configuration script Add README.md for static IPv4 configuration script --- SysInfoProject/NetworkStuffs/Linux/README.md | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 SysInfoProject/NetworkStuffs/Linux/README.md diff --git a/SysInfoProject/NetworkStuffs/Linux/README.md b/SysInfoProject/NetworkStuffs/Linux/README.md new file mode 100644 index 0000000..bda4ce2 --- /dev/null +++ b/SysInfoProject/NetworkStuffs/Linux/README.md @@ -0,0 +1,28 @@ +# 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: + From a65f00e185447d358827e0a13ae7fdb843fae131 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 23 Feb 2026 21:08:13 -0700 Subject: [PATCH 45/45] Enhance README with usage and configuration details Expanded the README with detailed usage instructions, parameters, rollback procedures, verification steps, exit codes, remote server warnings, requirements, license information, and contribution guidelines. --- SysInfoProject/NetworkStuffs/Linux/README.md | 156 +++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/SysInfoProject/NetworkStuffs/Linux/README.md b/SysInfoProject/NetworkStuffs/Linux/README.md index bda4ce2..53d8675 100644 --- a/SysInfoProject/NetworkStuffs/Linux/README.md +++ b/SysInfoProject/NetworkStuffs/Linux/README.md @@ -26,3 +26,159 @@ It includes full error handling, rollback capabilities, validation logic, and op 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 + +---