Shell
1#!/bin/bash
2#
3# Hetzner Cloud Server Info & Cost Optimizer
4#
5# Description:
6# Fetches all servers from your Hetzner Cloud account and analyzes their pricing.
7# For each server, it identifies cheaper server types with equal or better specs.
8# Results are exported to a tab-separated file (servers.txt) with cost savings.
9#
10# Setup:
11# 1. Create a .env file in the same directory with your Hetzner API token:
12# HETZNER_API_TOKEN=your_token_here
13# 2. Ensure jq and curl are installed
14# 3. Make the script executable: chmod +x get_server_info.sh
15#
16# Usage:
17# ./get_server_info.sh
18#
19# Output file (servers.txt) contains columns:
20# - Server name, type, IP, cores, RAM, disk, current price
21# - Cheaper alternative type, price, and potential savings (if available)
22#
23
24if [ -f ".env" ]; then
25 source .env
26else
27 echo "Error: .env file not found"
28 exit 1
29fi
30
31if [ -z "$HETZNER_API_TOKEN" ]; then
32 echo "Error: HETZNER_API_TOKEN not set in .env file"
33 exit 1
34fi
35
36OUTPUT_FILE="servers.txt"
37
38> "$OUTPUT_FILE"
39
40echo "Fetching servers from Hetzner Cloud API..."
41
42echo "Fetching available server types..."
43server_types_response=$(curl -s -H "Authorization: Bearer $HETZNER_API_TOKEN" "https://api.hetzner.cloud/v1/server_types")
44
45all_servers=""
46
47for page in 1 2 3; do # very basic pagination, adjust as needed
48 echo "Fetching servers page $page..."
49 api_response=$(curl -s -H "Authorization: Bearer $HETZNER_API_TOKEN" "https://api.hetzner.cloud/v1/servers?page=$page&per_page=50")
50
51 if [ $? -ne 0 ]; then
52 echo "Error: Failed to fetch servers from Hetzner API (page $page)"
53 exit 1
54 fi
55
56 if [ -z "$all_servers" ]; then
57 all_servers="$api_response"
58 else
59 all_servers=$(echo "$all_servers" | jq --argjson new "$api_response" '.servers += $new.servers')
60 fi
61done
62
63echo "$all_servers" | jq -r '.servers[] |
64 [
65 .name,
66 .server_type.name,
67 .public_net.ipv4.ip,
68 (.server_type.cores | tostring),
69 (.server_type.memory | tostring),
70 (.server_type.disk | tostring),
71 (.server_type.prices[0].price_monthly.gross)
72 ] | @tsv' | while IFS=$'\t' read -r name server_type ip cores ram_gb disk price; do
73
74 disk_gb="$disk"
75
76 price_formatted=$(printf "%.2f" "$price" | sed 's/\./,/')
77
78 cheaper_option=$(echo "$server_types_response" | jq -r --arg cores "$cores" --arg ram "$ram_gb" --arg disk "$disk" --arg current_price "$price" '
79 [.server_types[] |
80 select(
81 (.cores >= ($cores | tonumber)) and
82 (.memory >= ($ram | tonumber)) and
83 (.disk >= ($disk | tonumber)) and
84 (.prices[0].price_monthly.gross | tonumber) < ($current_price | tonumber)
85 ) |
86 {name: .name, price: (.prices[0].price_monthly.gross | tonumber)}] |
87 sort_by(.price) |
88 .[0] // empty |
89 [.name, (.price | tostring)] |
90 @tsv
91 ')
92
93 if [ -n "$cheaper_option" ]; then
94 cheaper_type=$(echo "$cheaper_option" | cut -f1)
95 cheaper_price=$(echo "$cheaper_option" | cut -f2)
96 cheaper_price_formatted=$(printf "%.2f" "$cheaper_price" | sed 's/\./,/')
97 savings=$(echo "$price - $cheaper_price" | bc)
98 savings_formatted=$(printf "%.2f" "$savings" | sed 's/\./,/')
99
100 echo "Processing: $name ($server_type) - Cheaper option available: $cheaper_type"
101 printf "%s\t%s\t%s\t%s\t%sGB\t%sGB\t%s\t%s\t%s\t%s\n" "$name" "$server_type" "$ip" "$cores" "$ram_gb" "$disk_gb" "$price_formatted" "$cheaper_type" "$cheaper_price_formatted" "$savings_formatted" >> "$OUTPUT_FILE"
102 else
103 echo "Processing: $name ($server_type) - Best price"
104 printf "%s\t%s\t%s\t%s\t%sGB\t%sGB\t%s\t-\t-\t-\n" "$name" "$server_type" "$ip" "$cores" "$ram_gb" "$disk_gb" "$price_formatted" >> "$OUTPUT_FILE"
105 fi
106done
107
108echo ""
109echo "Done! Results written to $OUTPUT_FILE"最后更新: 11月12日 10:03
Hetzner
评论 (0)
还没有评论,来说点什么吧~