📊

大量の回線のうち過去何ヶ月か使っていないSIMを割り出す

2024/10/10に公開

やりたいこと

保有するSIMの数が増えてくると、実はあんまり使ってないSIMもあるんじゃないか?と思って調べたくなることがあります。
一応、サービス利用履歴をCSVダウンロードすることもできますが、SIMの枚数がいっぱいあると結構大変です。
alt text
ダウンロードしたCSVをExcelで開いて、集計するのも結構面倒です。
ファイルのフォーマットとか・・・
alt text
こういった作業は定期的にやるケースがあると思うので、ある程度自動化したいですよね。

今回のブログでは、「ここnヶ月であんまり使ってないSIMを割り出す!」ということをSORACOM CLIを使ってやってみたいと思います。

前提

今回はmacOSを使って進めます。
(Windowsの場合は、PowerShellを使って進めることができます。ニーズがあれば、Windowsの場合の記事も書きます。)

準備

SORACOM-CLIをセットアップ

基本的にこちらの通り。

認証情報の準備

https://users.soracom.io/ja-jp/tools/cli/getting-started/?tab-2-1=selected#ステップ-2-認証情報を準備する

ここにも書いてある通り、SAM ユーザーの認証キーを使いましょう。ということで、こちら https://users.soracom.io/ja-jp/docs/sam/create-sam-user/ の手順に沿ってやっていきます。
認証キーは無くさないように大事にしまっておきましょう。

認証情報の保存

https://users.soracom.io/ja-jp/tools/cli/getting-started/?tab-2-1=selected#ステップ-3-認証情報を保存する

ここまで終わったらSORACOM CLIが使えるようになります。

練習

ターミナルを立ち上げます。

alt text

alt text

試しに、持っているSIMの一覧を引き出してみましょう。

soracom sims list

何かそれっぽいJSONが出てきたら大成功です。

alt text

本番

いよいよここからです。

結論から書きます。スクリプトは以下のとおりです。

こちらからダウンロードできます。

#!/bin/zsh

# デフォルトの日付設定
DEFAULT_FROM_DATE="2024-07-01"  # デフォルト開始日
DEFAULT_TO_DATE="2024-10-31"    # デフォルト終了日

# 引数が渡されていれば、それを使用。なければデフォルト値を使用
FROM_DATE=${1:-$DEFAULT_FROM_DATE}  # 第1引数が指定されていなければデフォルト値
TO_DATE=${2:-$DEFAULT_TO_DATE}      # 第2引数が指定されていなければデフォルト値

# UNIX秒に変換
FROM_UNIX=$(date -j -f "%Y-%m-%d" "$FROM_DATE" +%s)
TO_UNIX=$(date -j -f "%Y-%m-%d" "$TO_DATE" +%s)

# データ通信量が0のSIMを格納する配列
inactive_sims=()

# authkey,IDを取得
configure=$(soracom configure get)
authKeyId=$(echo $configure | jq -r '.authKeyId')
authKey=$(echo $configure | jq -r '.authKey')

# APIキーとトークンを取得
auth_info=$(soracom auth --auth-key-id "$authKeyId" --auth-key "$authKey" --token-timeout-seconds 3600)
apiKey=$(echo "$auth_info" | jq -r '.apiKey')
apiToken=$(echo "$auth_info" | jq -r '.token')

# 全てのSIMのIMSIを取得
all_sims=($(soracom sims list --fetch-all --api-key "$apiKey" --api-token "$apiToken" | jq -r '.[].profiles[].subscribers[].imsi'))
total_sims=${#all_sims[@]}  # 総SIM数

# プログレスバーの表示関数
display_progress() {
    local progress=$1
    local bar_width=50
    local filled=$((progress * bar_width / 100))
    local empty=$((bar_width - filled))
    
    printf "\r["
    printf "#%.0s" $(seq 1 $filled)
    printf " %.0s" $(seq 1 $empty)
    printf "] %d%%" $progress
}

# 各SIMのデータ通信量を確認
for ((i=0; i<total_sims; i++)); do
    imsi=${all_sims[$i]}
    
    # データ通信量を取得
    data_usage=$(soracom stats air get --imsi "$imsi" --from "$FROM_UNIX" --to "$TO_UNIX" --period "month" --api-key "$apiKey" --api-token "$apiToken" 2>> error.log)

    # エラーチェック
    if [[ $? -ne 0 ]]; then
        echo "IMSI: $imsi のデータ取得に失敗しました。" >> error.log
        continue
    fi

    # データ通信量が0の場合、配列に追加
    download=$(echo "$data_usage" | jq '.[].dataTrafficStatsMap[].downloadByteSizeTotal' | awk '{s+=$1} END {print s}')
    upload=$(echo "$data_usage" | jq '.[].dataTrafficStatsMap[].uploadByteSizeTotal' | awk '{s+=$1} END {print s}')

    if [[ "$download" -eq 0 && "$upload" -eq 0 ]]; then
        inactive_sims+=("$imsi")
    fi

    # 進捗率の表示
    progress=$(( (i + 1) * 100 / total_sims ))
    display_progress $progress
done

# 結果を表示
echo ""  # プログレスバーの改行
if [[ ${#inactive_sims[@]} -eq 0 ]]; then
    echo "全てのSIMがデータ通信を行っています。"
else
    echo "データ通信を行っていないSIM:"
    for sim in "${inactive_sims[@]}"; do
        echo "$sim"
    done
fi

使い方は以下のとおりです。

ダウンロードまたは上記内容を書いたファイルを保存したしたディレクトリに移動します。

cd ファイルを保存したディレクトリ

スクリプトファイルに実行権限を付与します。

chmod +x check_sim_data_usage.sh

実行するときは、以下のように実行します。

./check_sim_data_usage.sh 開始日 終了日

開始日と終了日は、YYYY-MM-DDの形式で指定してください。
例えば、2024年7月1日から2024年9月30日までのデータ通信がないSIMを調べる場合は、以下のように実行します。

./check_sim_data_usage.sh 2024-07-01 2024-09-30

実行結果は以下のようになります。

takao@TakaonoMacBook-Pro temp % ./check_sim_data_usage.sh 2024-07-01 2024-09-30
開始日: 2024-07-01
終了日: 2024-09-30
[##################################################  ] 100%
データ通信を行っていないSIM:
4401030000000000001
4401030000000000002
4401030000000000003
以下略

解説

集計期間の設定

はじめの部分は日付の設定です。
SORACOM APIを使う際は、日付はUNIX秒で指定する必要がありますが、人間が扱いやすい形式で指定して、script内でUNIX秒に変換しています。

一応、デフォルトの開始日と終了日を設定していますが、引数が渡されていればそれを使用するようにしていますので、数ヶ月経ってから実行する場合など同じスクリプトを使いまわすことができます。

# デフォルトの日付設定
DEFAULT_FROM_DATE="2024-07-01"  # デフォルト開始日
DEFAULT_TO_DATE="2024-10-31"    # デフォルト終了日

# 引数が渡されていれば、それを使用。なければデフォルト値を使用
FROM_DATE=${1:-$DEFAULT_FROM_DATE}  # 第1引数が指定されていなければデフォルト値
TO_DATE=${2:-$DEFAULT_TO_DATE}      # 第2引数が指定されていなければデフォルト値

# UNIX秒に変換
FROM_UNIX=$(date -j -f "%Y-%m-%d" "$FROM_DATE" +%s)
TO_UNIX=$(date -j -f "%Y-%m-%d" "$TO_DATE" +%s)

SORACOM CLIの認証情報取得

SORACOM CLIを使うとき、一つずつコマンドを実行していく場合は初期設定で使用した認証情報を用いてapi-keyとapi-tokenを取得するという処理が、毎回自動的に実施されます。
一方でこのapi-keyとapi-tokenの取得には1秒程度の時間がかかります。今回のユースケースのように、複数のコマンドを連続して実行する場合は、認証情報を取得しておいて再利用することで全体の実行時間を短縮できます。

ここでは、soracom configure getで取得した認証情報を使ってapi-keyとapi-tokenを取得して再利用できるように変数に格納しています。

# authkey,IDを取得
configure=$(soracom configure get)
authKeyId=$(echo $configure | jq -r '.authKeyId')
authKey=$(echo $configure | jq -r '.authKey')

# APIキーとトークンを取得
auth_info=$(soracom auth --auth-key-id "$authKeyId" --auth-key "$authKey" --token-timeout-seconds 3600)
apiKey=$(echo "$auth_info" | jq -r '.apiKey')
apiToken=$(echo "$auth_info" | jq -r '.token')

保有SIMの取得

soracom sims listコマンドで保有している全てのSIMの情報を取得します。
取得した情報はJSON形式で返ってくるので、jqコマンドを使って必要な情報(今回はSIMのIMSI)だけを取り出しています。
--fetch-allオプションをつけることで、全てのSIMを取得できます。
(これをつけない場合は、100件のみ取得されます。)
--fetch-all --api-key "$apiKey" --api-token "$apiToken"の部分は先ほど取得したapi-keyとapi-tokenを使っていこのコマンドを実行しています。

# 全てのSIMのIMSIを取得
all_sims=($(soracom sims list --fetch-all --api-key "$apiKey" --api-token "$apiToken" | jq -r '.[].profiles[].subscribers[].imsi'))
total_sims=${#all_sims[@]}  # 総SIM数

プログレスバーの表示

効率化してはいるものの、SIMの数が多い場合は処理が終わるまでに時間がかかることがあります。何も表示されないと不安になるので、進捗のプログレスバーを表示する関数を定義しています。
キャリッジリターン(\r)を使って、同じ行に表示されるようにしています。
終わった割合だけ、#が積み上がっていきます。

# プログレスバーの表示関数
display_progress() {
    local progress=$1
    local bar_width=50
    local filled=$((progress * bar_width / 100))
    local empty=$((bar_width - filled))
    
    printf "\r["
    printf "#%.0s" $(seq 1 $filled)
    printf " %.0s" $(seq 1 $empty)
    printf "] %d%%" $progress
}

SIMごとのデータ通信量の取得

先程のsoracom sims listで取得した全てのSIMのIMSIを使って、それぞれのSIMのデータ通信量を取得しています。
このコマンドはSIMのIMSIを指定して、指定した期間のデータ通信量を取得するコマンドです。
したがって、IMSIの数だけfor文で回して、それぞれのIMSIのデータ通信量を取得しています。

--imsiオプションでIMSIを指定して、--from--toで取得する期間を指定しています。
--periodオプションで取得する期間を指定しています。今回はmonthを指定しています。
2>> error.logはエラーが発生した場合、エラーログを出力するためのものです。

データを取得した後は、ダウンロード量とアップロード量を取得して、どちらも0の場合はinactive_simsという配列に追加しています。
ここまでの一連の処理が終わったところで、進捗率を表示して次のSIMに移ります。

# 各SIMのデータ通信量を確認
for ((i=0; i<total_sims; i++)); do
    imsi=${all_sims[$i]}
    
    # データ通信量を取得
    data_usage=$(soracom stats air get --imsi "$imsi" --from "$FROM_UNIX" --to "$TO_UNIX" --period "month" --api-key "$apiKey" --api-token "$apiToken" 2>> error.log)

    # エラーチェック
    if [[ $? -ne 0 ]]; then
        echo "IMSI: $imsi のデータ取得に失敗しました。" >> error.log
        continue
    fi

    # データ通信量が0の場合、配列に追加
    download=$(echo "$data_usage" | jq '.[].dataTrafficStatsMap[].downloadByteSizeTotal' | awk '{s+=$1} END {print s}')
    upload=$(echo "$data_usage" | jq '.[].dataTrafficStatsMap[].uploadByteSizeTotal' | awk '{s+=$1} END {print s}')

    if [[ "$download" -eq 0 && "$upload" -eq 0 ]]; then
        inactive_sims+=("$imsi")
    fi

    # 進捗率の表示
    progress=$(( (i + 1) * 100 / total_sims ))
    display_progress $progress
done

結果の表示

最後に、データ通信量が0のSIMのIMSIを表示しています。
forループの中でinactive_simsという配列に追加していたので、それを表示しています。

# 結果を表示
echo ""  # プログレスバーの改行
if [[ ${#inactive_sims[@]} -eq 0 ]]; then
    echo "全てのSIMがデータ通信を行っています。"
else
    echo "データ通信を行っていないSIM:"
    for sim in "${inactive_sims[@]}"; do
        echo "$sim"
    done
fi

以上、お疲れ様でした。

GitHubで編集を提案

Discussion