現場で使えるシェルスクリプト入門20:curlとjqで構築!Gemini APIを活用したAI自動応答スクリプト

シェルスクリプト IT

前回の記事(入門19)では、設定ファイルや共通関数を外部ファイルとして読み込み、コードの再利用性と安全性を高める「sourceコマンド(. コマンド)」について解説しました。

今回は、これまでに学習した知識(入門16の jq、入門18の curl、入門19の source)を使用して、「シェルスクリプトからAI(Gemini API)に自動で処理を投げ、回答を取得するAI自動応答スクリプト」を構築します!

LinuxやmacOSの標準ターミナル環境だけで、AIに要約やテキスト生成を依頼できるようになります。

シェルスクリプト×AI連携のメリット

なぜシェルスクリプトからAI APIを呼び出すのでしょうか?そこには以下のようなメリットがあります。

  • 環境構築が不要
    Pythonの仮想環境(venv)や各種ライブラリのインストールが不要で、コマンド(curl, jq)だけで即座に動くスクリプトが作成できます。
  • 既存のバッチ処理やCLI操作と直結できる
    「ログファイルをパースした結果をAIに渡してエラー要約を作成させる」「夜間バックアップの結果をAIに分析させる」といった運用自動化が簡単に組めます。
  • これまでの学習知識(curl, jq, source)がそのまま活きる
    source によるAPIキーの分離、curl によるPOSTリクエスト送信、jq によるレスポンスJSONの解読とテキスト抽出という、入門16〜19の知識で構築できます。jq について過去記事で未掲載の内容については補足を入れてあります。

AI自動応答サンプルスクリプト(ask_gemini.sh)

ここでは、APIキーを管理する設定ファイル(config.env)と、AIへ問い合わせを行うメインスクリプト(ask_gemini.sh)の2ファイル構成で作成します。

1. config.env(設定・APIキー管理ファイル):

# Gemini APIのAPIキー設定
GEMINI_API_KEY="YOUR_GEMINI_API_KEY_HERE"

2. ask_gemini.sh(AI自動応答メインスクリプト):

#!/bin/bash

# スクリプトを安全に実行するための基本設定
set -euo pipefail

# 💡 スクリプト自身の存在するディレクトリパスを取得(cron実行対策)
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
CONFIG_FILE="$SCRIPT_DIR/config.env"

# 1. 設定ファイルの存在確認と読み込み(sourceコマンド)
if [ ! -f "$CONFIG_FILE" ]; then
    echo "エラー: 設定ファイル ($CONFIG_FILE) が見つかりません。" >&2
    exit 1
fi

. "$CONFIG_FILE"

# 2. APIキーが未設定・初期値のままになっていないか判定
if [ -z "${GEMINI_API_KEY:-}" ] || [ "$GEMINI_API_KEY" = "YOUR_GEMINI_API_KEY_HERE" ]; then
    echo "エラー: config.env 内に有効な GEMINI_API_KEY が設定されていません。" >&2
    exit 1
fi

# 3. 引数(AIへの指示・プロンプト)の受け取り確認
PROMPT="${1:-}"
if [ -z "$PROMPT" ]; then
    echo "使用方法: $0 \"AIへの質問や指示テキスト\"" >&2
    exit 1
fi

echo "--- AI (Gemini) へ問合せ中... ---"

# 4. jq を使って安全にJSONリクエスト(ペイロード)を生成する
PAYLOAD=$(jq -n --arg msg "$PROMPT" '{contents: [{parts: [{text: $msg}]}]}')

# 5. Gemini APIのエンドポイントURLを定義(gemini-3.1-flash-liteを指定)
API_URL="https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent?key=${GEMINI_API_KEY}"

# 6. curl コマンドでPOSTリクエストを送信し、レスポンスJSONを受け取る
RESPONSE=$(curl -sS -H "Content-Type: application/json" -X POST -d "$PAYLOAD" "$API_URL")

# 7. jq コマンドでJSONからAIの回答テキストを取り出す
AI_TEXT=$(echo "$RESPONSE" | jq -r '.candidates[0].content.parts[0].text // empty')

# 8. 取得結果の判定と出力
if [ -z "$AI_TEXT" ]; then
    echo "エラー: AIからの回答取得に失敗しました。レスポンス内容:" >&2
    echo "$RESPONSE" | jq . >&2
    exit 1
fi

echo "--- [AIからの回答] ---"
echo "$AI_TEXT"

スクリプトの実行手順と事前準備

以下のステップで準備し、動作を確認します。

手順1. Gemini APIキーの取得と設定

Google AI Studio(https://aistudio.google.com/)からAPIキーを発行し、config.env ファイルの GEMINI_API_KEY="..." に貼り付けます。

手順2. 実行権限の付与

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

chmod +x ask_gemini.sh

手順3. スクリプトの実行

引数に質問文や指示メッセージを渡して実行します。

$ ./ask_gemini.sh "シェルスクリプトでログを自動要約するメリットを3点、簡潔に教えて"
--- AI (Gemini) へ問合せ中... ---
--- [AIからの回答] ---
シェルスクリプトでログを自動要約するメリットは以下の3点です。

1.  **異常の早期発見(効率化)**
    膨大なログからエラーや特定のキーワードを即座に抽出できるため、監視にかかる時間と労力を大幅に削減できます。
2.  **属人化の防止と継続性**
    手順がスクリプト化されることで、誰が実行しても同じ基準でログを分析でき、確認漏れなどのヒューマンエラーを防げます。
3.  **自動化による即時対応**
    cron等と組み合わせることで、夜間や休日でも定期的に要約レポートを生成し、障害発生時に即座に通知する仕組みを構築できます。

プログラムコードの詳細解説

スクリプト内で使用している主要な技術ポイントを詳しく解説します。

  • source コマンド(. )による認証情報の保護
    . "$CONFIG_FILE" でAPIキーを外部から読み込みます。スクリプト本体内に直接APIキーをハードコードしないため、コードをGitHubなどで共有しても認証情報が記載された外部ファイルを対象から除外することでAPIキーが漏洩しない安全な設計になります。
  • curl によるPOST通信
    curl -sS -H "Content-Type: application/json" -X POST -d "$PAYLOAD" "$API_URL" を使用し、ヘッダーにJSON形式を指定した上で、組み立てたリクエストデータ($PAYLOAD)を送信してAIのレスポンスを受け取ります。
  • jq -r によるネストされたテキスト抽出と // empty
    Gemini APIのレスポンスJSONは階層が深いため、jq -r '.candidates[0].content.parts[0].text // empty' と指定して、最深部にあるテキストデータを取り出します。
    末尾の // empty はオルタナティブ演算子 // と特殊値 empty の組み合わせです。APIエラー等で指定のキーパスが存在せず結果が null になった場合、通常は "null" という文字列が出力されてしまいます。末尾に // empty を添えることで null 文字列の出力を抑止して「空(長さゼロの文字列)」に変換でき、後続の if [ -z "$AI_TEXT" ]; then によるエラー判定が正確に動作するようになります。

安全なJSON生成を行う「jq -n –arg」オプションの解説

今回のスクリプトで最も重要な記述が PAYLOAD=$(jq -n --arg msg "$PROMPT" '{contents: [{parts: [{text: $msg}]}]}') です。入門16で解説したデータの「抽出・パース」とは異なり、ここでは jq の以下の特別なオプションを使用してゼロから安全なJSONを組み立てています。

  • -n(–null-input)オプションの機能
    通常の jq はファイルや標準入力から既存のJSONデータを読み込もうとします。しかし、-n オプションを付けると「入力データを必要とせず、nullから新しいJSON構造を出力・生成するモード」になります。これにより、jq コマンド単体で新規のJSONデータを作成できます。
  • –arg 変数名 値 オプションの機能(なぜ msg を渡すのか?)
    --arg 変数名 値(例: --arg msg "$PROMPT")は、シェルスクリプトの変数($PROMPT)を jq の内部で使える変数($msg)として定義・受け渡すオプションです。

    【なぜ msg を渡すのか?】
    jq の内部フィルター '{contents: [{parts: [{text: $msg}]}]}' の中で、$msg という変数名を使って元のプロンプト文字列(指示文)を JSON の text フィールドへ埋め込むためです。第一引数に jq 内で使う任意の識別子名(ここでは msg)を指定し、第二引数に渡したいシェル変数("$PROMPT")を指定します(※名前は任意のため --arg prompt "$PROMPT" として内部で text: $prompt と参照しても構いません)。

    また、この構文を使用することで、文章の中に改行や "(ダブルクォーテーション)などの特殊文字が含まれていても、jq が自動的にJSON規格に合わせた適切なエスケープ処理(\"\n 等への変換)を行ってくれます。

この2つのオプションを組み合わせることで、複雑なプロンプト文章であってもJSON構文を破壊することなく、1行で安全なJSONリクエストを作成できます。

シェルスクリプト連携時の落とし穴とエラーハンドリング

AI APIとシェルスクリプトを連携させる際、特に注意すべき「3つの落とし穴」とその対策です。

① 404 NOT_FOUND(モデル名指定ミス)

APIリクエスト時に "message": "models/gemini-1.5-flash is not found for API version v1beta" という 404 エラーが返ってくる場合、URLで指定しているモデル名(gemini-1.5-flash 等)がGoogle API側で非推奨または提供終了になっています。URLのモデル名を現在標準提供されているモデルに変更することで正常に通信できるようになります。

② 文字列エスケープ漏れによるJSON破壊

ヒアドキュメントや echo で直接文字列を連結してJSONを作成しようとすると、ユーザーが入力した文章に "(ダブルクォーテーション)や改行が含まれていた場合にJSONの構造が壊れ、APIから構文エラーが返ってきます。これを防ぐために、JSONの生成は前述の jq -n --arg の使用をお勧めします。

③ APIキーのGitHub漏洩と閲覧権限

config.env に記録したAPIキーをGitで誤ってコミット・公開してしまう事故が多発しています。Gitで管理する場合は .gitignore に追記(本記事の場合config.env) し、サーバー上では chmod 600 config.env と指定して自分以外のユーザーから読み取れないよう権限を制限してください。

まとめ

今回は、これまでに学んだ jqcurlsource の技術を使って、シェルスクリプトからGemini APIを自動呼び出しする「AI自動応答スクリプト」を構築しました。

シェルスクリプトだけでAIを活用した強力な自動化ツールを作成できます。ぜひ今回の構成をベースに、自作のバッチ処理やログ解析にAI連携を取り入れてみてください!

コメント

タイトルとURLをコピーしました