#!/bin/bash : <<=cut =pod =head1 NAME iothrottle - Limit IO to a given speed =head1 SYNOPSIS B [-i read-speed] [-o write-speed] I =head1 DESCRIPTION B limits B(2) and B(2) to a given speed. =head1 OPTIONS =over 4 =item B<-i> I Throttle B(2) to I bytes per second. To I you can append k, K, m, M, g, G to multiply by 1000, 1024, 1000000, 1048576 respectively. =item B<-o> I Throttle B(2) to I bytes per second. To I you can append k, K, m, M, g, G to multiply by 1000, 1024, 1000000, 1048576 respectively. =back =head1 EXAMPLE Copy mydir at 1MB/s: iothrottle -i 1M cp -a mydir/ /other/filesystem/ =head1 BUGS Not all program use B(2) and B(2) for I/O. These all use other methods: cp (to same filesystem), seq File a bug report when you find other programs: https://git.data.coop/tange/tangetools/issues =head1 ENVIRONMENT VARIABLES =over 9 =item $IOTHROTTLE_DEBUG=1 Turn on debugging. =back =head1 AUTHOR Copyright (C) 2024 Ole Tange, http://ole.tange.dk and Free Software Foundation, Inc. =head1 LICENSE Copyright (C) 2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or at your option any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . =head1 DEPENDENCIES B uses B. =head1 SEE ALSO B, B =cut _hex() { local hex=dummy echo $hex } _iothrottle.so() { local iothrottleso=$(mktemp) _hex | LC_ALL=C awk '{for (i=1; i<=length($0); i+=2) printf "%c", strtonum("0x" substr($0, i, 2))}' > "$iothrottleso" echo "$iothrottleso" } # Default values for input and output limits INPUT_LIMIT="" OUTPUT_LIMIT="" # Parse command-line arguments while [[ $# -gt 0 ]]; do case "$1" in -i) INPUT_LIMIT="$2" shift 2 ;; -o) OUTPUT_LIMIT="$2" shift 2 ;; *) break ;; esac done # Convert limits to bytes convert_to_bytes() { local value="$1" if [[ "$value" =~ ^[0-9]+K$ ]]; then value=$(( ${value%K*} * 1024 )) fi if [[ "$value" =~ ^[0-9]+k$ ]]; then value=$(( ${value%k*} * 1000 )) fi if [[ "$value" =~ ^[0-9]+M$ ]]; then value=$(( ${value%M*} * 1024 * 1024 )) fi if [[ "$value" =~ ^[0-9]+m$ ]]; then value=$(( ${value%m*} * 1000 * 1000 )) fi echo "$value" } IOTHROTTLE_READ=$(convert_to_bytes "$INPUT_LIMIT") IOTHROTTLE_WRITE=$(convert_to_bytes "$OUTPUT_LIMIT") # Export environment variables export IOTHROTTLE_READ=${IOTHROTTLE_READ:-0} export IOTHROTTLE_WRITE=${IOTHROTTLE_WRITE:-0} # Preload the library and execute the remaining command _so=$(_iothrottle.so) if [ IOTHROTTLE_DEBUG = 1 ] ; then echo LD_PRELOAD=$_so LD_PRELOAD=$_so "$@" else LD_PRELOAD=$_so "$@" rm $_so fi