Skip to content

Instantly share code, notes, and snippets.

@OutOfThisPlanet
Last active August 8, 2025 23:26
Show Gist options
  • Select an option

  • Save OutOfThisPlanet/a7133fb05d7a1fd4d3667609238e9ef7 to your computer and use it in GitHub Desktop.

Select an option

Save OutOfThisPlanet/a7133fb05d7a1fd4d3667609238e9ef7 to your computer and use it in GitHub Desktop.
Multi-threaded IPTV stream checker
#!/bin/bash
# Variables
path=$(pwd)
sname=$0
wfile="$path/working.m3u"
# Setup colors
cyan='\e[0;36m'
green='\033[92m'
red='\e[1;31m'
yellow='\e[0;33m'
orange='\e[38;5;166m'
# Check if temp directory exists
if [[ ! -d $path/temp ]]; then
mkdir "$path/temp" >/dev/null 2>&1
fi
# Clean any files from previous run in temp folder
rm -rf "$path/temp/*" >/dev/null 2>&1
# Function to handle process cleanup on exit or Ctrl+C
function cleanup() {
# Kill all background processes
echo "Cleaning up orphaned processes..."
for pid in $(cat "$path/temp/pids.txt" 2>/dev/null); do
if ps -p "$pid" > /dev/null; then
kill "$pid" >/dev/null 2>&1
fi
done
rm -f "$path/temp/pids.txt" # Clean the pid list file
exit 1
}
# Trap cleanup function to run on script exit or interrupt (Ctrl+C)
trap cleanup EXIT INT
# Multi-threaded stream checking
function check_stream() {
local chkf=$1
local i=$2
local srvnmb=$3
local wfile=$4
local unique_id=$5 # unique identifier for each stream check
# Generate a unique temp file for each process
local temp_stream_file="$path/temp/stream_$unique_id"
local temp_pid_file="$path/temp/pid_$unique_id"
chkurl=$(echo "$chkf" | head -c 4)
case "$chkurl" in
http|rtmp|HTTP)
wget -q "$chkf" -O "$temp_stream_file" &
pid=$!
echo $pid >> "$path/temp/pids.txt" # Save pid to file
sleep 10
rpid=$(ps -p "$pid" -o pid= | awk '{print$1}')
if [[ "$rpid" == "$pid" ]]; then
kill $pid
fi
if [[ ! -f "$temp_stream_file" ]]; then
echo -e "$yellow" "Error reading captured file"
else
stsz=$(wc -c "$temp_stream_file" | awk '{print$1}')
if [[ "$stsz" -le "100" ]]; then
echo -e "$green" "Link:$yellow $i$green of :$yellow$srvnmb$green is$red OFF"
else
echo -e "$green" "Link:$yellow $i$green of :$yellow$srvnmb$green is$green ON"
writefile "$chkf" "$wfile"
fi
fi
esac
# Cleanup
rm -rf "$temp_stream_file" >/dev/null 2>&1
rm -rf "$temp_pid_file" >/dev/null 2>&1
}
# Function that processes and writes results to file
function writefile() {
local chkf=$1
local wfile=$2
# checks if tool already created previously an m3u file
if [[ -f "$wfile" ]]; then
gturlline=$(grep -n "$chkf" < $path/temp/1 | tr ":" "\n" | sed -n 1p)
defline=$((gturlline-1))
stdata=$(sed -n "$defline p" < $path/temp/1)
echo "$stdata" >> "$wfile"
echo "$chkf" >> "$wfile"
echo "" >> "$wfile"
else
echo "#EXTM3U" > "$wfile"
echo "" >> "$wfile"
gturlline=$(grep -n "$chkf" < $path/temp/1 | tr ":" "\n" | sed -n 1p)
defline=$((gturlline-1))
stdata=$(sed -n "$defline p" < $path/temp/1)
echo "$stdata" >> "$wfile"
echo "$chkf" >> "$wfile"
echo "" >> "$wfile"
fi
}
# Function to test stream with parallelism
function teststream() {
wrn="0"
if [[ -f "$wfile" ]]; then
exts="1"
else
exts="0"
fi
ckf=$(grep "<item>" < $path/temp/1)
if [[ ! -z "$ckf" ]]; then
xmlproc
fi
glnk=$(grep -F "http" < "$path/temp/1" | sed '/EXTINF/d' | sed '/EXTM3U/d' | awk '!a[$0]++' | sed '/^$/d')
echo "$glnk" | tr " " "\n" > "$path/temp/2"
srvnmb=$(wc -l "$path/temp/2" | awk '{print$1}')
rm -rf "$path/temp/stream" >/dev/null 2>&1
rm -rf "$path/temp/pid.tmp" >/dev/null 2>&1
# Multi-threaded checking using background processes
for i in $(seq "$srvnmb"); do
chkf=$(sed -n "${i}p" < "$path/temp/2")
unique_id=$i # Unique identifier for each stream check
check_stream "$chkf" "$i" "$srvnmb" "$wfile" "$unique_id" &
done
# Wait for all background processes to finish
wait
if [[ "$exts" == "0" ]]; then
if [[ -f "$wfile" ]]; then
echo ""
echo -e "$green" "Job Finished"
echo ""
echo -e "$yellow" "You can find your new iptv list in :"
echo -e "$orange" "$wfile"
exit 1
fi
else
echo ""
echo -e "$green" "Job Finished"
echo ""
echo -e "$yellow" "Your iptv list was updated in :"
echo -e "$orange" "$wfile"
exit 1
fi
}
# Case for remote m3u file
function remotef() {
wget "$file" -O "$path/temp/1" >/dev/null 2>&1
flsz=$(wc -c "$path/temp/1" | awk '{print$1}')
if [[ "$flsz" -le "10" ]]; then
echo -e "$yellow" "The remote link is down or the file size is too small to be an m3u iptv list file"
echo ""
exit 0
fi
teststream
}
# Case for local m3u file
function localf() {
if [[ ! -f "$file" ]]; then
echo -e "$yellow" "The file you specified does not exist"
echo -e "$yellow" "in :$green $file "
echo ""
echo -e "$yellow" "Make sure you wrote the right path of it"
exit 1
fi
cp "$file" "$path/temp/1" >/dev/null 2>&1
flsz=$(wc -c "$path/temp/1" | awk '{print$1}')
if [[ "$flsz" -le "10" ]]; then
echo -e "$yellow" "The file you specified is too small to be an m3u iptv file"
exit 0
fi
teststream
}
# Main execution starts here
file="$1"
echo "$file" | grep "http" >/dev/null 2>&1
if [ "$?" -eq "0" ]; then
remotef
else
localf
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment