Bash Scripts

Create Incremental Backup with Rsync

#!/bin/bash
# Create incremental backups using rsync with hard links
# Current impementation meant for daily backups

# TODO: Implement arguments for customizability- number of backups, date interval, source and destination folders

current_date=$(date)
to_backup=("/etc" "/home" "/root" "/var" "/srv" "/opt")
# number of backups to keep
backup_backlog=10

# Change to backup folder
cd /backup

# rotate backups
# wildcard allows for missing days due to downtime (using async scheduler)
rm -rf backup.*.${backup_backlog}
for (( log_number=$backup_backlog; log_number >= 2; log_number-- )); do
    log_date=$(ls | grep backup.*.$((${log_number}-1)) | cut -d'.' -f 2)
    # If the destination folder doesn't have the max number of backups (backup_backlog), filenaming gets weird
    # This makes sure that if any of the backup directories are missing, an empty file with the right name is added
    # New empty file keeps naming convention consistent
    if [ ! -d "backup.${log_date}.$(( ${log_number} - 1 ))" ]; then
        touch "backup.$(date --date="$(date) -${log_number} days" '+%F').$(( ${log_number} - 1 ))"
        log_date=$(ls | grep backup.*.$((${log_number}-1)) | cut -d'.' -f 2)
    fi
    mv "backup.${log_date}.$(( ${log_number} - 1 ))" "backup.${log_date}.${log_number}"
done
cp -al "backup.$(ls | grep backup.*.0 | cut -d'.' -f 2).0" "backup.$(ls | grep backup.*.0 | cut -d'.' -f 2).1"

# make new backup
rsync -a --dry-run --delete --exclude="/home/*/.cache" ${to_backup[@]} "backup.$(ls | grep backup.*.0 | cut -d'.' -f 2).0"
# Keeps naming convention consistent
mv "backup.$(ls | grep backup.*.0 | cut -d'.' -f 2).0" "backup.$(date '+%F').0/"

Check if certain files or directories have changed

#!/bin/bash

if ! [ -f /var/opt/org_hashes ]; then
        cur_file="/var/opt/org_hashes"
else
        cur_file="/var/opt/check_hashes"
        rm -f $cur_file
fi

echo "$(sha256sum /etc/passwd)" >>              ${cur_file}
echo "$(sha256sum /etc/shadow)" >>              ${cur_file}
echo "$(sha256sum /etc/ssh/sshd_config)" >>     ${cur_file}
echo "$(sha256sum /etc/crontab)" >>             ${cur_file}

systemctl | grep service >> /tmp/service_list
echo "$(sha256sum /tmp/service_list)" >>        ${cur_file} 
rm -f /tmp/service_list

for file in $(echo $PATH | sed 's/:/ /g'); do
        ls -l $file > /tmp/$(echo $file | sed 's/\//_/g')
        sha256sum /tmp/$(echo $file | sed 's/\//_/g') >> $cur_file
        rm -f /tmp/$(echo $file | sed 's/\//_/g')
done


echo "`sha256sum $(which sshd)`" >>             ${cur_file}
echo "`sha256sum $(which ps)`" >>               ${cur_file}
echo "`sha256sum $(which netstat)`" >>          ${cur_file}
echo "`sha256sum $(which lsof)`" >>             ${cur_file}
echo "`sha256sum $(which ss)`" >>               ${cur_file}

if [ -f /var/opt/check_hashes ]; then
        if [ "$(sha256sum /var/opt/check_hashes | cut -d ' ' -f 1)" = "$(sha256sum /var/opt/org_hashes | cut -d ' ' -f 1)" ]; then
                echo "Files are unchanged"
        else
                echo "Files Changed!"
        fi
fi

Generate an arbitrary number of test files in a specified folder

#!/bin/sh
# Generates an arbitrary number of files in a given directory
# Default content of files is "test", but user can provide a custom string or the content of a file

# Make sure all vars are empty
unset -v target_dir
unset -v count
unset -v content

show_help() {
	echo "
Usage: ./filegen <-d Directory> <-n Count> [-c String | Path]
  -d:\tTarget directory
  -n:\tNumber of files to generate
  -c:\tContent of generated file, can be custom string or content of given file (defaults to "test")

For Example: ./filegen.sh -d test_directory -n 100 -c "Test Content"

  -h:\tDisplays this message
"
}

# get all flags
while getopts ":c:d:n:h" opt; do
	case "${opt}" in
		d) target_dir=$OPTARG;;
		n) count=$OPTARG;;
		c) content=$OPTARG;;
		h) show_help; exit 0;;
		*)
			echo 'Incorrect Usage:' >&2
			show_help
			exit 1
	esac
done

shift "$(( OPTIND - 1 ))"

# Make sure target directory and count were specified
if [ -z "$target_dir" ] || [ -z "$count" ]; then
	echo 'Incorrect usage: Please specify target directory (-d) and file count (-n)'
	show_help
	exit 1
fi

# Check if $content is a file, if so read file contents into variable
if [ -f "$content" ]; then
	if ! [ -w "$content" ]; then
		echo 'Insufficient Privileges, using content "test"'
		content='test'
	else
		echo "Using file content from: '$content'"
		content="$(cat $content)"
	fi
fi

# If $content wasn't a file or file was empty, make sure content variable is populated
if [ -z "$content" ]; then
	content='test'
fi

# check if count is an int
case $count in
	''|*[!0-9]*) echo "$count is not an integer!"; exit 1;;
	*) continue
esac

# If existing directory, make sure there are permissions
if [ -d $target_dir ]; then
	if ! [ -w $target_dir ]; then
		echo "Permission denied!"
		exit 1
	fi
fi

# Make directory
if mkdir -p $target_dir 2>/dev/null; then
	# If the directory is made, make sure there are no pre-existing test files
	cd $target_dir
	rm test_*.txt 2> /dev/null
	continue
else
	# Fails, usually means bad permissions
	echo 'Cannot create directory!'
	exit 1
fi

# POSIX shell compatible for loop
i=1
while [ "$i" -le "$count" ]; do
	echo "$content" > test_${i}.txt
	i=$((i+1))
done
unset -v i

echo "Done creating ${count} files!"
exit 0

Windows Scripts

Powershell

Find Listening TCP Services

# Find all open Ports and report the local address, local port, remote address, remote port, and Owning Process

$connections = Get-NetTCPConnection | sort-object State, LocalAddress, OwningProcess | Where-Object { $_.LocalAddress -notlike '*:*' }
$connections | Format-Table -AutoSize LocalAddress, LocalPort, RemoteAddress, RemotePort, State, @{
    Label = "Owning Process"
    Expression={(Get-Process -Id $_.OwningProcess)}
}

Command Prompt

Delete files older than X days

REM Windows batch file to delete all files in a specific folder older than x days
REM Based on script from https://www.howtogeek.com/131881/how-to-delete-files-older-than-x-days-on-windows/

REM Get folder to clear out and time restriction
set /p "folder=Enter folder to clear out: "

REM Check if folder exists
if not exist %folder%\* goto notexist

REM Enter how old in days the file must be to be deleted then lists the files in the folder
REM If the input is invalid, catch it and quit
set /p "UserInput=How old should the deleted files be (in days)? "
set /a days=%UserInput%

if %days% EQU 0 (
	echo Deletion Failed. Check Syntax.
	pause
	goto quit
) else (
    forfiles -p %folder% -s -m *.* -d -%days% -c "cmd /c echo @file"
	pause
)

REM Ask user if they want to delete the listed files
set /p "choice=Delete these files? [Y/N]: "

if /I %choice%=="Y" goto delete
goto nodelete

:nodelete
echo Not deleting files.
goto quit

:delete
REM Delete files in specified folder
echo Deleting files
forfiles -p %folder% -s -m *.* -d -(Number of days) -c "cmd /c del @path"
goto quit

:notexist
echo Folder does not exist
goto quit

:quit
pause