Skip to content

Instantly share code, notes, and snippets.

@pratikbin
Created June 28, 2025 22:13
Show Gist options
  • Save pratikbin/09f338e07ef52430608d68d4d9b425e8 to your computer and use it in GitHub Desktop.
Save pratikbin/09f338e07ef52430608d68d4d9b425e8 to your computer and use it in GitHub Desktop.
#!/bin/bash
# --- Configuration ---
SSHFS_MOUNT_DIR="/root/sshfs"
TEST_DIR_NAME="sshfs_speed_test"
FULL_TEST_DIR="${SSHFS_MOUNT_DIR}/${TEST_DIR_NAME}"
# Large file settings
LARGE_FILE_COUNT=2
LARGE_FILE_SIZE_MB=512 # Each file will be 512MB
TOTAL_LARGE_FILE_SIZE_MB=$((LARGE_FILE_COUNT * LARGE_FILE_SIZE_MB))
# Small file settings
SMALL_FILE_COUNT=5000 # Number of small files
SMALL_FILE_SIZE_KB=10 # Each small file will be 10KB
TOTAL_SMALL_FILE_SIZE_MB=$(( (SMALL_FILE_COUNT * SMALL_FILE_SIZE_KB) / 1024 )) # Convert to MB for info
# --- Colors for better output ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# --- Functions ---
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
# Function to check if SSHFS is mounted
check_mount() {
if ! mountpoint -q "${SSHFS_MOUNT_DIR}"; then
log_error "SSHFS directory '${SSHFS_MOUNT_DIR}' is not a mount point or does not exist."
log_error "Please ensure SSHFS is mounted before running this script."
exit 1
fi
log_info "SSHFS mount point '${SSHFS_MOUNT_DIR}' verified."
}
# Function to clean up previous test directories
cleanup_previous_test() {
if [ -d "${FULL_TEST_DIR}" ]; then
log_warning "Previous test directory '${FULL_TEST_DIR}' found. Removing..."
rm -rf "${FULL_TEST_DIR}"
if [ $? -ne 0 ]; then
log_error "Failed to remove previous test directory. Please check permissions."
exit 1
fi
log_success "Previous test directory removed."
fi
}
# Function to create test directory
create_test_directory() {
log_info "Creating test directory: ${FULL_TEST_DIR}"
mkdir -p "${FULL_TEST_DIR}"
if [ $? -ne 0 ]; then
log_error "Failed to create test directory. Check permissions for '${SSHFS_MOUNT_DIR}'."
exit 1
fi
log_success "Test directory created."
}
# Function to perform large file write test
test_large_file_write() {
log_info "--- Starting Large File Write Test ---"
log_info "Creating ${LARGE_FILE_COUNT} large files, each ${LARGE_FILE_SIZE_MB}MB..."
cd "${FULL_TEST_DIR}" || { log_error "Failed to change directory."; exit 1; }
START_TIME=$(date +%s.%N)
for i in $(seq 1 ${LARGE_FILE_COUNT}); do
log_info "Writing large_file_${i}.bin..."
# Use conv=fdatasync to ensure data is written to disk, not just cached
dd if=/dev/urandom of=large_file_${i}.bin bs=1M count=${LARGE_FILE_SIZE_MB} status=none
if [ $? -ne 0 ]; then
log_error "Failed to write large_file_${i}.bin."
cd - > /dev/null # Go back to original directory
exit 1
fi
done
END_TIME=$(date +%s.%N)
DURATION=$(echo "${END_TIME} - ${START_TIME}" | bc)
SPEED=$(echo "scale=2; ${TOTAL_LARGE_FILE_SIZE_MB} / ${DURATION}" | bc)
log_success "Large File Write: Wrote ${TOTAL_LARGE_FILE_SIZE_MB}MB in ${DURATION} seconds."
log_success "Large File Write Speed: ${SPEED} MB/s"
echo "Large_File_Write_Speed_MB/s: ${SPEED}" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
cd - > /dev/null # Go back to original directory
log_info "--- Large File Write Test Completed ---"
}
# Function to perform large file read test
test_large_file_read() {
log_info "--- Starting Large File Read Test ---"
log_info "Reading ${LARGE_FILE_COUNT} large files, each ${LARGE_FILE_SIZE_MB}MB..."
cd "${FULL_TEST_DIR}" || { log_error "Failed to change directory."; exit 1; }
START_TIME=$(date +%s.%N)
for i in $(seq 1 ${LARGE_FILE_COUNT}); do
log_info "Reading large_file_${i}.bin..."
# Read from the file to /dev/null to measure read speed without disk write overhead
dd if=large_file_${i}.bin of=/dev/null bs=1M status=none
if [ $? -ne 0 ]; then
log_error "Failed to read large_file_${i}.bin."
cd - > /dev/null
exit 1
fi
done
END_TIME=$(date +%s.%N)
DURATION=$(echo "${END_TIME} - ${START_TIME}" | bc)
SPEED=$(echo "scale=2; ${TOTAL_LARGE_FILE_SIZE_MB} / ${DURATION}" | bc)
log_success "Large File Read: Read ${TOTAL_LARGE_FILE_SIZE_MB}MB in ${DURATION} seconds."
log_success "Large File Read Speed: ${SPEED} MB/s"
echo "Large_File_Read_Speed_MB/s: ${SPEED}" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
cd - > /dev/null
log_info "--- Large File Read Test Completed ---"
}
# Function to perform small file write test
test_small_file_write() {
log_info "--- Starting Small File Write Test ---"
log_info "Creating ${SMALL_FILE_COUNT} small files, each ${SMALL_FILE_SIZE_KB}KB..."
cd "${FULL_TEST_DIR}" || { log_error "Failed to change directory."; exit 1; }
START_TIME=$(date +%s.%N)
for i in $(seq 1 ${SMALL_FILE_COUNT}); do
# Use head -c to create small files quickly without /dev/urandom overhead
head -c ${SMALL_FILE_SIZE_KB}K </dev/urandom > small_file_${i}.txt
# Alternative for empty files: touch small_file_${i}.txt
if [ $? -ne 0 ]; then
log_error "Failed to write small_file_${i}.txt."
cd - > /dev/null
exit 1
fi
done
END_TIME=$(date +%s.%N)
DURATION=$(echo "${END_TIME} - ${START_TIME}" | bc)
FILES_PER_SEC=$(echo "scale=2; ${SMALL_FILE_COUNT} / ${DURATION}" | bc)
log_success "Small File Write: Created ${SMALL_FILE_COUNT} files in ${DURATION} seconds."
log_success "Small File Write Speed: ${FILES_PER_SEC} files/second"
echo "Small_File_Write_Files/s: ${FILES_PER_SEC}" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
cd - > /dev/null
log_info "--- Small File Write Test Completed ---"
}
# Function to perform small file read test
test_small_file_read() {
log_info "--- Starting Small File Read Test ---"
log_info "Reading ${SMALL_FILE_COUNT} small files, each ${SMALL_FILE_SIZE_KB}KB..."
cd "${FULL_TEST_DIR}" || { log_error "Failed to change directory."; exit 1; }
START_TIME=$(date +%s.%N)
# Use find and xargs to read each file. This simulates directory listing + file access.
find . -maxdepth 1 -name "small_file_*.txt" -print0 | xargs -0 -I {} dd if={} of=/dev/null bs=1K count=${SMALL_FILE_SIZE_KB} status=none
# Alternative for just counting: find . -maxdepth 1 -name "small_file_*.txt" -exec cat {} > /dev/null \;
# The dd method is more accurate for measuring actual read throughput.
if [ $? -ne 0 ]; then
log_error "Failed to read small files."
cd - > /dev/null
exit 1
fi
END_TIME=$(date +%s.%N)
DURATION=$(echo "${END_TIME} - ${START_TIME}" | bc)
FILES_PER_SEC=$(echo "scale=2; ${SMALL_FILE_COUNT} / ${DURATION}" | bc)
log_success "Small File Read: Read ${SMALL_FILE_COUNT} files in ${DURATION} seconds."
log_success "Small File Read Speed: ${FILES_PER_SEC} files/second"
echo "Small_File_Read_Files/s: ${FILES_PER_SEC}" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
cd - > /dev/null
log_info "--- Small File Read Test Completed ---"
}
# --- Main Script Execution ---
log_info "Starting SSHFS Speed Test for '${SSHFS_MOUNT_DIR}'"
echo "--- SSHFS Speed Test Results ($(date)) ---" > "${SSHFS_MOUNT_DIR}/test_results.txt"
check_mount
cleanup_previous_test
create_test_directory
log_info "--- Test Parameters ---"
log_info "Large Files: ${LARGE_FILE_COUNT} x ${LARGE_FILE_SIZE_MB}MB (Total: ${TOTAL_LARGE_FILE_SIZE_MB}MB)"
log_info "Small Files: ${SMALL_FILE_COUNT} x ${SMALL_FILE_SIZE_KB}KB (Total: ${TOTAL_SMALL_FILE_SIZE_MB}MB)"
echo "" >> "${SSHFS_MOUNT_DIR}/test_results.txt" # Add a blank line for readability
# Run Tests
test_large_file_write
echo "" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
test_large_file_read
echo "" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
test_small_file_write
echo "" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
test_small_file_read
echo "" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
# Final Cleanup
log_info "Cleaning up test directory: ${FULL_TEST_DIR}"
rm -rf "${FULL_TEST_DIR}"
if [ $? -ne 0 ]; then
log_error "Failed to clean up test directory. Manual removal may be required."
else
log_success "Test directory cleaned up."
fi
log_success "SSHFS Speed Test Completed!"
log_info "Results are also saved in: ${SSHFS_MOUNT_DIR}/test_results.txt"
echo "--- End of Test ---" >> "${SSHFS_MOUNT_DIR}/test_results.txt"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment