タグ: シェルスクリプト Page 4 of 6

ChatGPTによるシェルスクリプト。(DNSレコード問い合わせ-2-)

続・DNSレコードを問い合わせるシェルスクリプト

このスクリプトを発展させました。

スクリプト内容

  • dns.sh
#!/bin/bash

# ドメイン名の入力を求める
read -p "ドメイン名を入力してください: " query

# 入力が未設定の場合の処理
if [ -z "$query" ]; then
    # デフォルトのDNSで問い合わせを行う
    default_dns=$(dig +short A +short myip.opendns.com @resolver1.opendns.com)
    echo "デフォルトのDNS: $default_dns"
else
    # ユーザーが指定したDNSで問い合わせを行う
    read -p "問い合わせるDNSを指定してください(空白Enterの場合はデフォルトのDNSを使用します): " dns_server

    if [ -z "$dns_server" ]; then
        dns_server="@resolver1.opendns.com"
    else
        dns_server="@$dns_server"
    fi

    # Aレコードの問い合わせ
    a_record=$(dig +short A $query $dns_server)
    if [ -z "$a_record" ]; then
        a_record="未設定です"
    fi

    # TXTレコードの問い合わせ
    txt_record=$(dig +short TXT $query $dns_server)
    if [ -z "$txt_record" ]; then
        txt_record="未設定です"
    fi

    # MXレコードの問い合わせ
    mx_record=$(dig +short MX $query $dns_server)
    if [ -z "$mx_record" ]; then
        mx_record="未設定です"
    fi

    # レコードの問い合わせの種類を選択するプロンプトを表示
    echo "問い合わせるレコードの種類を選んでください:"
    echo "1. Aレコード"
    echo "2. TXTレコード"
    echo "3. MXレコード"
    echo "4. すべてのレコード"

    # レコードの種類をユーザーに選択させる
    read -p "選択してください (1, 2, 3, または 4): " record_type

    # ユーザーの選択に応じて問い合わせ結果を表示
    case $record_type in
        1)
            # Aレコードの問い合わせ結果を表示
            echo "Aレコード: $a_record"
            ;;
        2)
            # TXTレコードの問い合わせ結果を表示
            echo "TXTレコード: $txt_record"
            ;;
        3)
            # MXレコードの問い合わせ結果を表示
            echo "MXレコード: $mx_record"
            ;;
        4)
            # すべてのレコードを表示
            echo "Aレコード: $a_record"
            echo "TXTレコード: $txt_record"
            echo "MXレコード: $mx_record"
            ;;
        *)
            # 無効な選択が入力された場合のエラーメッセージ
            echo "無効な選択です。1, 2, 3, または 4 を入力してください。"
            ;;
    esac
fi

追加した内容

「どこのDNSサーバに問い合わせを行うか」です。

  • ローカルDNSに問い合わせたい場合
  • 冗長化を組んでいるDNSのセカンダリーに反映されているかを確認したい場合
  • 世界的なDNSでもレコードが引けるか

を確認するケースが多々あったので、これを追加です。今回ChatGPTが指定したのはopendnsなので、

DNSサーバ名主なIPアドレス
Google Public DNS8.8.8.8
Cloudflare DNS1.1.1.1
Quad99.9.9.9
Level 3 DNS4.2.2.1

といったDNSサービスを変数に入れればデフォルトを変えてくれます。

ChatGPTによるシェルスクリプト。(DNSレコード問い合わせ)

運用時に多用するdigコマンド。オプション入力が面倒なので、スクリプトをChatGPTに書いてもらいました。

スクリプトの動き

  1. ドメイン名をプロンプトで入力させる。
  2. どのレコードを問い合わせるのかをプロンプトで表示。
  3. 2の結果に従い、結果を返す。

スクリプトの内容

  • dns.sh
#!/bin/bash

# ドメイン名の入力を求める
read -p "ドメイン名を入力してください: " query

# 入力が未設定の場合の処理
if [ -z "$query" ]; then
    echo "エラー: ドメイン名が設定されていません。"
else
    # Aレコードの問い合わせ
    a_record=$(dig +short A $query)
    if [ -z "$a_record" ]; then
        a_record="未設定です"
    fi

    # TXTレコードの問い合わせ
    txt_record=$(dig +short TXT $query)
    if [ -z "$txt_record" ]; then
        txt_record="未設定です"
    fi

    # MXレコードの問い合わせ
    mx_record=$(dig +short MX $query)
    if [ -z "$mx_record" ]; then
        mx_record="未設定です"
    fi

    # レコードの問い合わせの種類を選択するプロンプトを表示
    echo "問い合わせるレコードの種類を選んでください:"
    echo "1. Aレコード"
    echo "2. TXTレコード"
    echo "3. MXレコード"
    echo "4. A / TXT / MXレコード"

    # レコードの種類をユーザーに選択させる
    read -p "選択してください (1, 2, 3, または 4): " record_type

    # ユーザーの選択に応じて問い合わせ結果を表示
    case $record_type in
        1)
            # Aレコードの問い合わせ結果を表示
            echo "Aレコード: $a_record"
            ;;
        2)
            # TXTレコードの問い合わせ結果を表示
            echo "TXTレコード: $txt_record"
            ;;
        3)
            # MXレコードの問い合わせ結果を表示
            echo "MXレコード: $mx_record"
            ;;
        4)
            # A / TXT / MXレコードを表示
            echo "Aレコード: $a_record"
            echo "TXTレコード: $txt_record"
            echo "MXレコード: $mx_record"
            ;;
        *)
            # 無効な選択が入力された場合のエラーメッセージ
            echo "無効な選択です。1, 2, 3, または 4 を入力してください。"
            ;;
    esac
fi

入力後、

chmod +x dns.sh

で実行権を付与。

実行例

./dns.sh 
ドメイン名を入力してください: google.co.jp
問い合わせるレコードの種類を選んでください:
1. Aレコード
2. TXTレコード
3. MXレコード
4. A / TXT / MXレコード
選択してください (1, 2, 3, または 4): 4
Aレコード: 142.250.199.99
TXTレコード: "v=spf1 -all"
MXレコード: 0 smtp.google.com.

今後足したい機能

  1. 問い合わせ先のDNSサーバの変数指定
  2. レコードを増やす
  3. 空エンター時の挙動

など、伸ばす余地はあります。

曜日を判別するmot_d。(Ubuntuシェルスクリプト)

概要

サーバにターミナル経由でログインした際に表示されるメッセージ、motd(Message of the Day)。

「特定の日時・曜日をを判別して、その条件を満たしたときにメッセージを表示することはできないか?」

ということでシェルスクリプトを書いてみました。

動作を確認した環境

  • Ubuntu 20.04

スクリプト内容

  • /etc/update-motd.d/02-Friday_Check(または既存のupdate-motdに追記します)

※管理者権限で追記する必要があります。

#!/bin/bash

# 現在の言語ロケールを保存します。
original_locale=$(locale | grep "LANG=" | cut -d= -f2)

# ロケールを英語に修正します。
export LANG="en_US.UTF-8"

# ロサンゼルス(カリフォルニア)の曜日を調べます。
day_of_week=$(TZ="America/Los_Angeles" date +"%A")

# 金曜日だった場合のみメッセージを表示します。
if [ "$day_of_week" == "Friday" ]; then
    echo "Today is Friday in California."
fi

# 元の言語ロケールに戻します。
export LANG="$original_locale"

追記後、

sudo chmod +x /etc/update-motd.d/02-Friday_Check

として、実行権限を付与してください。(既存スクリプトに追記する場合はその限りではありません)

スクリプトの動き

サーバにログインした際に

  1. 現在の言語ロケールを保存します。
  2. 言語ロケールを英語に修正します。(曜日の変数をFridayに固定しているため)
  3. タイムゾーンをチェックして、カリフォルニアで金曜日かどうかを判別します。
  4. PST(太平洋標準時)/PDT(太平洋夏時間)で金曜日の時間帯に
  5. Today is Friday in California. を表示します。
  6. 最後に、保存された言語ロケールへと戻します。

まとめ

今回は単に文字列を判別するだけ。ですが、月末時の処理や保守更新などの応用が利きそうです。

Linux:シェルスクリプトで天気表示。

概要

Linuxのコマンドラインで天気を知りたい状況があったので、簡単なスクリプトを書きました。

前提

  • Linux機がインターネットに繋がっていること。
  • ansiweatherがインストールされていること。

Ubuntuでのansiweatherインストール方法

以下のコマンドを実行します。

sudo aptitude install ansiweather
# 筆者の好みでaptitudeを用いています。必要に応じてaptを使ってください。

スクリプト

  • getweather.sh

以下の内容を教義・信仰に沿ったエディタで記載します。

#!/bin/bash

# ユーザーに都市名を尋ねる
echo "都市名を入力してください:"
read city

# ansiweatherコマンドを実行して天気情報を表示
echo "ansiweatherの情報:"
ansiweather -l "$city"

# curlコマンドを使用してwttr.inから天気情報を表示
echo "wttr.inの情報:"
curl wttr.in/"$city?lang=ja"
  • 実行権限付与
chmod +x getweather.sh

スクリプトの動き

  • スクリプト実行
./getweather.sh
  • 実行結果

都市名を入力します。(Tokyo, Londonなど)

入力後、以下のように1行で現在の天気の概要、アスキーアートで3日の予報が出てきます。

Torの出口ノードリストからのWebアクセスを遮断する設定。(Mod_Securityとの連携)

こちらの記事の続きとなります。

Torの出口ノードリストを抽出するスクリプトと、既に稼働済みの不審なIPアドレスをブロックするスクリプトを連携させます。

前提

こちらにあるように、

  • Mod_Security導入済み
  • エラー検知時にブロックする設定をバーチャルサイトに設定済み

となります。

また、先日の記事である、

  • Tor出口ノードリストを抽出スクリプトがCron化されているものとします。

スクリプト

  • negativelist.sh
#!/bin/bash

# 読み込むログのディレクトリとファイル名を変数指定
log_dir="/var/lib/redmine/log"
log_file="error.log"

# シェルスクリプトから抽出したTorの出口ノードリストを指定
tor_list_dir="/path/to/directory"  # tor_list.txtのディレクトリを指定
tor_list_file="sorted_ip_addresses$(date +%Y%m%d).txt"

# 除外するIPアドレスをファイルで指定
# 自分のNWなど、偽陽性を防ぐために記載したアドレスのリストです。
exclude_ips_file="/path/to/directory/exclude_ips.txt"

# ログファイルからIPアドレスを抽出して重複を排除し、ファイルに保存します。
cd "$log_dir"
awk 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) { print substr($0, RSTART, RLENGTH) }' "$log_file" | sort -u > "$log_dir/suspicious_ip/suspicious_ip.$(date +%Y%m%d)"
chown www-data:www-data "$log_dir/suspicious_ip/suspicious_ip.$(date +%Y%m%d)"

# 過去のIPアドレスを読み込んで重複を排除し、ファイルに保存します。
cat "$log_dir/suspicious_ip/suspicious_ip."2* | sort -u > "$log_dir/suspicious_ip_all.txt"
chown www-data:www-data "$log_dir/suspicious_ip_all.txt"

# 新たにリストに書き起こすと同時にTorの出口ノードリストを読み込んで重複を排除し、negativelist.txtに追加します。
cat "$log_dir/suspicious_ip_all.txt" "$tor_list_dir/$tor_list_file" | sort -u > /etc/apache2/sites-available/negativelist.txt

# 除外するIPアドレスをファイルから削除します。
while IFS= read -r exclude_ip; do
  sed -i "/$exclude_ip/d" /etc/apache2/sites-available/negativelist.txt
done < "$exclude_ips_file"

# Apacheを再起動します。
systemctl restart apache2.service

あとはこちらをroot権限でCron登録。

設定後の動き

以下のように動きます。

  1. 指定のログファイルからエラーとなったIPアドレスのみを抽出します。
  2. 全てのIPアドレスを統合し、重複を排除してsuspicous_ip_all.txtとして抽出します。
  3. suspicous_ip_all.txtとtor_list_fileを統合し、negativelist.txtとして作成します。(これらのIPアドレスからのアクセスに対しては全て403を返します)
  4. negativelist.txtから除外IPアドレスを取り除きます。
  5. Webサービスを再起動します。

ひとまず、WAFとの連携ができました。

IPアドレス抽出スクリプト。(Torの出口リスト)

必要があったので、スクリプトを書きました。

スクリプトの動き

  1. 公開されているTor出口リストをダウンロード。
  2. IPアドレスのみを抽出。
  3. 重複を排除してソート。

スクリプト内容

  • tor_exit_hodes.sh
#!/bin/bash

# 出口ノードリストのURL
TOR_EXIT_LIST_URL="https://check.torproject.org/exit-addresses"

# ダウンロード先ファイル名
OUTPUT_FILE="exit_nodes.$(date +%Y%m%d).txt"

# curlを使用してリストをダウンロード
curl -o "$OUTPUT_FILE" "$TOR_EXIT_LIST_URL" 

##curl -o "$OUTPUT_FILE" "$TOR_EXIT_LIST_URL" >/dev/null 2>&1
##cron処理などを行う場合はこちらを使います。

# ダウンロードが成功したかどうかを確認
if [ $? -eq 0 ]; then
  echo "Tor出口ノードリストをダウンロードしました。ファイル: $OUTPUT_FILE"
else
  echo "ダウンロード中にエラーが発生しました。"
  exit 1
fi

# IPアドレスのみを抽出し、ソートして出力
awk '/^ExitAddress/ {print $2}' "$OUTPUT_FILE" | sort | uniq | tee sorted_ip_addresses$(date +%Y%m%d).txt 

##awk '/^ExitAddress/ {print $2}' "$OUTPUT_FILE" | sort | uniq > sorted_ip_addresses$(date +%Y%m%d).txt >/dev/null 2>&1
##cron処理などを行う場合はこちらを使います。

これで、IPアドレスのみが抽出されますので、apache/nginxやFiwawall/WAFとの連携が容易になります。

今後の動き

  1. Cron化
  2. Mod_Securityとの連携

などやっていきます。

Mod_Securityが検知したIPアドレスの自動遮断スクリプト・修正。

以下のスクリプトを修正しました。

このスクリプトの主な動き

  1. Mod_Securityが検知したエラーログからIPアドレスのみを抜き出す。
  2. 重複を排除した上でsuscpicious_ip.YYYYMMDD形式で保存。
  3. 全てのsuscpicious_ip.YYYYMMDDを統合する。
  4. ここからnegativelist.txtを作成する。
  5. negativelist.txtの中に疑陽性(自身のアクセス元)のIPを排除する。
  6. Webサービスを再起動する。

そうして、「一度でもMod_Securityが疑わしいと検知すれば、次回以降のアクセスを許さない」という、言わば“ONE OUTS”システムを採用しています。

この可読性を高めました。

スクリプトが動く前提

  • ApacheとMod_Securityを運用している。
  • 以下のように、「negativelist.txt」に記録されたIP全てをブロックするようにしている。

apacheバーチャルサイト設定の抜粋

# Mod Security
SecRuleEngine On
## ModSecurity有効化
SecRequestBodyInMemoryLimit 524288000
SecRequestBodyLimit 524288000
## ファイルのアップロードをできるようにします。
    # ネガティブリスト
    SecRule REMOTE_ADDR "@pmFromFile negativelist.txt" "phase:1,id:2,deny,msg:'Negativelisted IP address'"

修正したスクリプト

※ 教義・信仰に沿ったエディタで記載します。

  • negativelist.sh
#!/bin/bash
# このシェルスクリプトは、変数で定義したエラーログからIPアドレスを抽出し、
# suspicious_ipディレクトリに保存し、その後、特定のIPアドレスを削除して
# /etc/apache2/sites-available/negativelist.txtに書き込むものです。

# 読み込むログのディレクトリとファイル名を変数指定
log_dir="/var/lib/redmine/log"
log_file="error.log"

# 除外するIPアドレスをファイルで指定
exclude_ips_file="/path/to/exclude_ips.txt"

# IPアドレスを抽出して重複を排除し、ファイルに保存
cd "$log_dir"
awk 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) { print substr($0, RSTART, RLENGTH) }' "$log_file" | sort | uniq > "$log_dir/suspicious_ip/suspicious_ip.$(date +%Y%m%d)"
chown www-data:www-data "$log_dir/suspicious_ip/suspicious_ip.$(date +%Y%m%d)"

# 過去のIPアドレスを読み込んで重複を排除し、ファイルに保存
cat "$log_dir/suspicious_ip/suspicious_ip."2* | sort | uniq > "$log_dir/suspicious_ip_all.txt"
chown www-data:www-data "$log_dir/suspicious_ip_all.txt"

# 新たにリストに書き起こす
cat "$log_dir/suspicious_ip_all.txt" > /etc/apache2/sites-available/negativelist.txt

# 除外するIPアドレスをファイルから削除
while IFS= read -r exclude_ip; do
  sed -i "/$exclude_ip/d" /etc/apache2/sites-available/negativelist.txt
done < "$exclude_ips_file"

# Apacheを再起動
systemctl restart apache2.service
  • 除外するIPアドレスリスト

※ 教義・信仰に沿ったエディタで作成します。

  • exclude_ips.txt 記載例
192.168.0.1
172.28.0.1
# 一行ずつ記載

記載後の設定

  • スクリプトの所有者変更
sudo chown root:root negativelist.sh
  • スクリプトの実行権付与
sudo chmod 744 negativelist.sh
  • cron登録
sudo crontab -e -u root
  • cron内容
0 6 * * * /home/manualmaton/bin/negativelist.sh

これによって、スクリプトを変数化。他のサーバへの転用を行いやすくしました。

ChatGPTによるRubyスクリプト。(エラーログ検索)

割とシンプルながら、障害などの特定を効率よくするためのスクリプトを書いてもらいました。

質問

以下の通りです。

以下を満たすスクリプトを書いてください。

1. プロンプトにてエラーログをフルパスで質問
1-1. エラーログが見つからなければ「ファイルがありません」を返して終了
2. プロンプトにて検索したい単語を指定
3. 検索単語にて行数を表示
4. 「○件見つかりました。該当する行を表示しますか?」でy/n確認
4-1. nの場合は処理を終了
4-2. yの場合は該当行を表示して終了

結果

ほぼ一発で想定通りの動きを見せるスクリプトを書いてもらいました。

# 1. プロンプトにてエラーログをフルパスで質問
print "エラーログのフルパスを入力してください: "
error_log_path = gets.chomp

# 1-1. エラーログが見つからなければ「ファイルがありません」を返して終了
unless File.exist?(error_log_path)
  puts "ファイルがありません"
  exit
end

# 2. プロンプトにて検索したい単語を指定
print "検索したい単語を入力してください: "
search_word = gets.chomp

# 3. 検索単語にて行数を表示
line_numbers = []
File.open(error_log_path, "r") do |file|
  file.each_line.with_index(1) do |line, line_number|
    line_numbers << line_number if line.include?(search_word)
  end
end

puts "#{line_numbers.length}件見つかりました。"

# 4. 「○件見つかりました。該当する行を表示しますか?」でy/n確認
unless line_numbers.empty?
  print "該当する行を表示しますか? (y/n): "
  display_lines = gets.chomp.downcase
  if display_lines == "y"
    File.open(error_log_path, "r") do |file|
      file.each_line.with_index(1) do |line, line_number|
        if line_numbers.include?(line_number)
          puts "行 #{line_number}: #{line.chomp}"
        end
      end
    end
  else
    exit
  end
else
  exit
end

エディタに記述、保存後に

ruby search_log.rb

を実行。

これで、

  • 怪しそうな箇所の行数
  • その詳細

などを絞ることが可能になり、ここからの加工も容易になります。

ChatGPTによるシェルスクリプト(パッケージの自動更新)の問題点と修正。

この記事の更に続きとなります。

以前作成したスクリプトに問題点があったので修正します。

問題点詳細

アップデートするパッケージによってはコンフィグを残すか否かをアップデート中に聞いてきます。

このプロンプトが表示されるとスクリプトは停止。処理を手動で中断して実行する羽目になります。

これを回避するため、以下のように修正いたしました。

修正差分

-    aptitude -y full-upgrade | tee $upgraded_packages >/dev/null
+    DEBIAN_FRONTEND=noninteractive aptitude -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" full-upgrade | tee $upgraded_packages >/dev/null

修正した処理の詳細

※chatGPTの回答なので信頼性は各自ご判断ください。

  1. DEBIAN_FRONTEND=noninteractive : DEBIAN_FRONTEND 環境変数に noninteractive を設定し、aptitude コマンドを非対話モードで実行します。これにより、パッケージの更新時に表示される確認メッセージを自動的に承認することができます。
  2. aptitude -y : aptitude コマンドに -y オプションを指定して、すべての質問に対して自動的に yes を返答するようにします。
  3. -o Dpkg::Options::="--force-confdef" : dpkg コマンドに --force-confdef オプションを指定して、パッケージがインストールされる際に必要なデフォルトの設定値を使用するように指定します。
  4. -o Dpkg::Options::="--force-confold" : dpkg コマンドに --force-confold オプションを指定して、既存のコンフィグファイルを保持するように指定します。
  5. full-upgrade : aptitude コマンドの full-upgrade オプションを指定して、すべてのパッケージを最新バージョンに更新します。
  6. | tee $upgraded_packages >/dev/null : 更新されたパッケージのリストを一時ファイルに保存します。パイプライン演算子 | を使用して、aptitude コマンドの出力を tee コマンドに送信し、同時に一時ファイルに書き込むように指定します。>/dev/null を追加することで、標準出力を無効化し、結果を表示しないようにします。

修正後のスクリプト全文

#!/bin/bash

# インストールされているパッケージの一覧を取得して別ファイルに出力します。
now1=$(date +%Y%m%d)
dpkg-query -W > installed_packages_$now1.txt

# aptitude updateを行います。
aptitude update

# updateの結果:
if aptitude search '~U' | grep -q '^i'; then
    # 対象パッケージ,変更前バージョン,変更後のバージョン を記入した日付付きのファイルを作成。
    now1=$(date +%Y%m%d)
    upgraded_packages=$(mktemp)

    # パッケージのキャッシュをクリアした上でパッケージアップグレードを実施。
    aptitude clean
    DEBIAN_FRONTEND=noninteractive aptitude -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" full-upgrade | tee $upgraded_packages >/dev/null

    # パッケージ一覧からの差分を別ファイルで作成。(実行日の日付を付与)
    new_packages=$(mktemp)
    dpkg-query -W > $new_packages
    diff -u installed_packages_$now1.txt $new_packages > package_diff_$now1.txt

   # 新しいパッケージ名を取得
   DIFF_FILE="package_diff_$now1.txt"
   NEW_PACKAGES=$(grep -E "^\+[^+]" $DIFF_FILE | awk '{print $1}' | cut -c 2-)

   # 変更されたパッケージの数と、新しいバージョンのパッケージ名のリストを表示
   UPDATED_PACKAGES=$(echo "$NEW_PACKAGES" | wc -l)
   echo "$UPDATED_PACKAGES 件のパッケージに変更がありました。以下のパッケージが更新されました:"
   echo "$NEW_PACKAGES"

    # checkrestartを実行して結果を取得
    now=$(date +%Y%m%d)
    checkrestart_output=$(checkrestart)

    # サービスを再起動する必要のあるプロセスを抽出してファイルに出力
    restart_services=$(echo "$checkrestart_output" | awk '/^(These are the systemd services|These are the initd scripts)/{flag=1;next}/^$/{flag=0}flag' | awk '{print $NF}' | sort -u)

    if [[ -n "$restart_services" ]]; then
        # ファイル名に日付を追加
        now2=$(date +%Y%m%d)
        filename="restart_services_$now2.txt"

        echo "以下のサービスを再起動してください:" >> "$filename"
        echo "$checkrestart_output" | awk '/^(These are the systemd services|These are the initd scripts)/{flag=1;next}/^$/{flag=0}flag' | grep -v "restart$" >> "$filename"
        echo "$checkrestart_output" | awk '/^(These are the systemd services|These are the initd scripts)/{flag=1;next}/^$/{flag=0}flag' | grep "restart$" >> "$filename"

        echo "以下のサービスを再起動してください:"
        echo "$checkrestart_output" | awk '/^(These are the systemd services|These are the initd scripts)/{flag=1;next}/^$/{flag=0}flag' | grep -v "restart$"
        echo "$checkrestart_output" | awk '/^(These are the systemd services|These are the initd scripts)/{flag=1;next}/^$/{flag=0}flag' | grep "restart$"


    else
        echo "再起動するサービスはありません"
    fi
fi

これでコンフィグを残すか否かのアップデートでも停止することなく動きましたが、肝心の

  • どのパッケージがコンフィグを残すか否か求められたか
  • その差分は何か

などが不明。なので、改善点はまだまだです。

Webサーバ:メモリ漸増への対処。(cronによる監視とWebサービス再起動)

概要

AWSで使っているWebサーバのメモリ使用量が漸増していくため、以下の処置を施しました。

実行環境

  • Ubuntu 20.04を稼働しているWebサーバ
  • メモリは4GB

さっくりとした手順

  1. メモリ使用量をトリガーとして、閾値を超えたらWebサービスの再起動を行うスクリプトを作成。
  2. このスクリプトをCron化。

スクリプト作成

管理者権限で以下を作成します。

  • memory_monitor.sh
#!/bin/bash

# メモリ使用量の閾値を設定する(ここではメガバイト単位で指定)
threshold=3584

# ログの保存パスと名前を設定する
log_path="/var/log/"
log_name="restart.log"

# 現在のメモリ使用量を取得する
mem_used_before=$(free -m | awk 'NR==2{print $3}')

# メモリ使用量が閾値を超えた場合にWebサービスの再起動を行う
if [ "$mem_used_before" -gt "$threshold" ]; then
    systemctl restart httpd
    # 極端な話、reboot と指定することでシステムそのものの再起動も可能です
    mem_used_after=$(free -m | awk 'NR==2{print $3}')
    mem_used_diff=$((mem_used_after - mem_used_before))
    echo "httpd service restarted on $(date). Memory usage difference: $mem_used_diff MB" >> "${log_path}${log_name}"
fi

作成後、実行権限を付与します。

sudo chmod 744 memory_monitor.sh

cron登録

sudo crontab -e -u root
  • 登録内容
*/15 * * * * /path/to/directory/memory_monitor.sh
# 格納したパスを指定します
# 15分おきに実行としています。

今後の課題

これはあくまでも対処療法。根本的なボトルネックの究明は継続して行います。

Page 4 of 6

Powered by WordPress & Theme by Anders Norén