Skip to content

Instantly share code, notes, and snippets.

@TaylanTatli
Created March 29, 2026 15:31
Show Gist options
  • Select an option

  • Save TaylanTatli/ad3ce56d47a46254a4bc32201685a862 to your computer and use it in GitHub Desktop.

Select an option

Save TaylanTatli/ad3ce56d47a46254a4bc32201685a862 to your computer and use it in GitHub Desktop.
Progressbar script for portainer
#!/usr/bin/env bash
sudo -v || exit 1
# Portainer PID
PID=$(pgrep portainer)
if [ -z "$PID" ]; then
echo "❌ Error: Portainer is not running..."
exit 1
fi
echo "-------------------------------------------------------------------"
echo " 🚀 Portainer Download Progress "
echo "-------------------------------------------------------------------"
sudo strace -s 4096 -e write -f -p $PID 2>&1 | \
grep --line-buffered -oE "[0-9a-f]{12} (Downloading .*MB|Download complete|Extracting|Pull complete)" | \
python3 -u -c "
import sys, re
try:
def clean_ansi(text):
return re.sub(r'\x1b\[[0-9;]*[mK]', '', text)
layers = {}
BAR_INNER_WIDTH = 40
def build_line(layer_id, inner_content, status_text):
fill_count = len(inner_content.replace(' ', ''))
scaled_fill = int(fill_count * (BAR_INNER_WIDTH / 50))
if scaled_fill > BAR_INNER_WIDTH: scaled_fill = BAR_INNER_WIDTH
bar_fill = '■' * scaled_fill
bar_empty = '・' * (BAR_INNER_WIDTH - scaled_fill)
return f'{layer_id} [ {bar_fill}{bar_empty} ] {status_text}'
while True:
line = sys.stdin.readline()
if not line: break
clean_line = clean_ansi(line).strip()
if not clean_line: continue
layer_id = clean_line[:12]
content = clean_line[12:].strip()
display = ''
if 'complete' in content or 'Extracting' in content:
status = 'Done!' if 'complete' in content else 'Extracting...'
display = build_line(layer_id, '=' * 50, status)
elif 'Downloading' in content:
start = content.find('[')
end = content.rfind(']')
if start != -1 and end != -1:
raw_inner = content[start+1:end]
size_match = re.search(r'\]\s+(.*MB)', content)
size_info = size_match.group(1) if size_match else ''
display = build_line(layer_id, raw_inner, f'Downloading ({size_info})')
else:
display = f'{layer_id} {content}'
else:
display = f'{layer_id} {content}'
if layer_id not in layers:
layers[layer_id] = len(layers)
print('')
diff = len(layers) - layers[layer_id]
sys.stdout.write(f'\033[{diff}A\r\033[K{display.ljust(110)}\033[{diff}B')
sys.stdout.flush()
except KeyboardInterrupt:
sys.exit(0)
"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment