📚

Pythonスクリプト作成:Linuxサーバの設定を変更し、その差分を取得する

2023/10/04に公開

はじめに

本記事では、Pythonを用いてLinuxサーバのresolv.confファイルのDNS設定を変更し、その変更前後の設定内容とその差分を取得するスクリプトについて紹介します。サーバ・ネットワーク運用における設定変更のオペレーションを自動化する際の一例として、またスクリプトの作成手法としての参考としてお読みいただければと思います。
 

記事の取り組み内容

  • Pythonのインストール方法について学ぶ。
  • Pythonのnetmikoライブラリを用いたSSH接続の基本を理解する。
  • LinuxサーバのDNS設定を変更するPythonスクリプトを作成し、実行する。
  • スクリプト実行により得られた設定変更前後の内容とその差分をファイルとして保存する方法を学ぶ。
     

概略

  1. Pythonのインストール
  2. pipの確認
  3. Netmikoのインストール
  4. スクリプトの作成
  5. スクリプトの実行
  6. ログファイルの確認

 

検証環境

検証はホストPCと仮想マシンに構築したLinuxサーバ間で行っています。仮想マシンのネットワーク接続はホストPCを介してNATモードで行われています。

  • ホストOS: Windows 10
  • 仮想化ソフトウェア: VMware Workstation 16 Player
  • ゲストOS (仮想マシン): CentOS 7.9

 

1.Pythonのインストール

Pythonの公式サイトからWindows用のPythonをダウンロードします。
特に迷うところは無いと思いますが、インストーラを実行する際に、"Add Python to PATH"のオプションを選択してください。コマンドプロンプトから直接Pythonを実行できるようになります。


最新の安定版は3.11だったため、このバージョンをインストールしました。
 


記事の手順はWindows環境に基づいています。従って、Downloadsの中からWindowsを選択しました。
 


使用しているPCは64-bit対応なので、"Download Windows installer (64-bit)" を選択しました。
 


Pythonをコマンドプロンプトから実行できるようにするため、"Add Python to PATH"を選択しました。
 


この画面が表示されれば、インストールは正常に完了しています。
 

 

2.pipの確認

インストールが完了したら、コマンドプロンプトを開き、pip --version を実行してpipが正しくインストールされていることを確認します。

 

3.Netmikoのインストール

netmikoは、ネットワーク機器へのSSH接続を簡単に行うためのPythonライブラリです。
pipを使用してNetmikoをインストールします。コマンドプロンプトで以下のコマンドを実行します。

 

4.スクリプトの作成

こちらのスクリプトは制御文のないシンプルなもので、その内容はコメントで説明していますので、ここでは詳しい説明は割愛します。

今回、Pythonスクリプトはresolv_conf_change.pyというファイル名で保存します。

resolv_conf_change.py

from netmiko import ConnectHandler
import os
from datetime import datetime

# デバイス情報の設定
device = {
    'device_type': 'linux',
    'ip': '192.168.111.5',
    'username': 'xxxx',
    'password': 'xxxxxxxxxx',
    'session_log': 'netmiko_session.log', # エラー確認用
    } 

connection = ConnectHandler(**device)

# 事前の設定内容を取得
pre_output = connection.send_command('cat /etc/resolv.conf')

# LinuxのDNSセカンダリ設定変更コマンド
change_commands = [
    "sed -i 's/nameserver 8.8.8.8/nameserver 1.1.1.1/g' /etc/resolv.conf"
]

for cmd in change_commands:
    connection.send_command(cmd)

# 事後の設定内容を取得
post_output = connection.send_command('cat /etc/resolv.conf')


# 一時ファイルに保存
cmd_pre_safe = f'''cat <<EOL | tee /tmp/pre_config.txt
{pre_output}
EOL
'''
connection.send_command_timing(cmd_pre_safe)

cmd_post_safe = f'''cat <<EOL | tee /tmp/post_config.txt
{post_output}
EOL
'''
connection.send_command_timing(cmd_post_safe)




# diffの取得
diff_output = connection.send_command('diff /tmp/pre_config.txt /tmp/post_config.txt')

# 一時ファイルの削除
connection.send_command('rm -f /tmp/pre_config.txt /tmp/post_config.txt')

# 事前、事後の設定内容をそれぞれ保存
current_time = datetime.now()
formatted_date = current_time.strftime('%Y%m%d%H%M')
pre_filename = f"{device['ip']}_{formatted_date}_pre.log"
post_filename = f"{device['ip']}_{formatted_date}_post.log"
diff_filename = f"{device['ip']}_{formatted_date}_diff.log"
pre_filepath = f"C:\\Users\\xxxx\\OneDrive\\デスクトップ\\{pre_filename}"
post_filepath = f"C:\\Users\\xxxx\\OneDrive\\デスクトップ\\{post_filename}"
diff_filepath = f"C:\\Users\\xxxx\\OneDrive\\デスクトップ\\{diff_filename}"

with open(pre_filepath, "w") as file:
    file.write(pre_output)
with open(post_filepath, "w") as file:
    file.write(post_output)
with open(diff_filepath, "w") as file:
    file.write(diff_output)

connection.disconnect()

print(f"設定変更前の内容が{pre_filename}に、設定変更後の内容が{post_filename}に、差分が{diff_filename}に保存されました。")


補足1: モジュールのインポートについて

from netmiko import ConnectHandler
netmikoは、ネットワーク機器へのSSH接続を容易にするPythonライブラリです。ConnectHandlerは、このライブラリの中のクラスで、機器への接続やコマンドの実行に使用します。本スクリプトではLinuxサーバへのSSH接続やコマンド実行にConnectHandlerを活用しています。

from datetime import datetime
datetimeモジュールは、日付や時間の操作を行うモジュールであり、この中にもdatetimeというクラスが存在します。スクリプトでは、現在の日時を取得してファイル名として利用するためにdatetime.now()メソッドを活用しています。

補足2:resolv.conf設定内容を一時ファイルに書き出す必要性

初めは、下記のようにdiffコマンドとプロセス置換<()を使って、直接設定の変更前後の内容を比較しようと試みましたが上手くいかなかったため、変更前後の設定内容を一時的なファイルに保存する方法を採用しました。

補足3:device_typeについて

例えばCiscoのネットワーク機器を対象にする場合は、下記にようにdevice_typeを変更します。

 

5. スクリプトの実行

コマンドプロンプトにて、スクリプトが保存されているディレクトリに移動し、以下のコマンドでスクリプトを実行します。

 

6.デスクトップでログファイルの確認

スクリプトが正しく実行されると、デスクトップに .log 形式のファイルが生成されています。DNSセカンダのアドレスが変更されていることが分かります。

設定変更前:192.168.111.5_202310041132_pre.log
設定変更後:192.168.111.5_202310041132_post.log
差分:192.168.111.5_202310041132_diff.log

 

最後に

この記事は、以前のネットワーク運用での手動作業の非効率さとミスのリスクを感じ、それを改善するための試みとして実践した内容を基にしています。特にConfig取得などの単純作業は手動での実施には問題がありますが、当然全ての作業を自動化すべきでは無いとも考えています。この記事はスクリプト作成の一例となりますので、セキュリティや適用範囲などについては、各環境の要件やルールを適切に考慮し、十分に検討してください。

また、私はプログラマーではないため、技術的に拙い部分や、お作法的にまずい部分もあるかもしれませんが、その点ご容赦いただければと思います。

Discussion