🐈

Go 言語で実装する PC 監視ツール:スクリーンショットを自動保存

2023/06/24に公開

はじめに

PC の監視は、セキュリティや運用の観点から重要なタスクの一つです。定期的なスクリーンショットを取得して保存することで、システムの状況を確認したり、異常状態の証拠を収集したりすることができます。しかし、この作業を手動で行うのは面倒で、なによりヒューマンエラーが生じる可能性もあります。

そこで今回は、Go 言語を使用してスクリーンショットを自動的に撮影し、それを別のドライブに移動するプログラムを作成します。さらに、そのプログラムを定期的に実行することで、PC の監視を自動化します。

1. スクリーンショットを撮る

スクリーンショットを撮影するコードを作成します。
スクリーンショット撮るには、github.com/kbinani/screenshot というパッケージを使用します。

package main

import (
	"fmt"
	"image/png"
	"os"
	"time"

	"github.com/kbinani/screenshot"
)

func main() {
	// アクティブなディスプレイの数を取得します
	n := screenshot.NumActiveDisplays()

	// すべてのディスプレイについて
	for i := 0; i < n; i++ {
		// i番目のディスプレイの領域(大きさと位置)を取得します
		bounds := screenshot.GetDisplayBounds(i)

		// i番目のディスプレイのスクリーンショットを撮ります
		img, err := screenshot.CaptureRect(bounds)
		if err != nil {
			panic(err)
		}

		// 現在の日時を取得します
		now := time.Now()
		// 日時を文字列に変換します("YYYYMMDDhhmmss"形式)
		dateTimeStr := now.Format("20060102150405")

		// ファイル名を作成します(日時を最初に付けます)
		fileName := fmt.Sprintf("%s_%d_%dx%d.png", dateTimeStr, i, bounds.Dx(), bounds.Dy())
		file, _ := os.Create(fileName)

		// スクリーンショットをPNG形式でファイルに書き込みます
		png.Encode(file, img)

		// ファイルを閉じます
		file.Close()

		// どのスクリーンショットを保存したかを出力します
		fmt.Printf("Saved screen #%d: %s\n", i, fileName)
	}
}

このコードでは、PC の全てのディスプレイからスクリーンショットを撮影し、それをファイルとして保存します。たとえば 2 つのディスプレイを使用している場合は 2 つのスクリーンショットが生成されます。
ファイル名には現在の日時("YYYYMMDDhhmmss" 形式)とディスプレイの番号およびディスプレイサイズが含まれるようになっています。

2. スクリーンショットを移動する

次に、撮影したスクリーンショットを移動します。以下に該当するコードの追加を示します。

package main

import (
	"fmt"
	"image/png"
	"io"
	"os"
	"path/filepath"
	"time"

	"github.com/kbinani/screenshot"
)


func main() {
	// ...省略

	for i := 0; i < n; i++ {
		// ...省略

		// 新しいパスを作成します(Windows で D ドライブを想定しています)
		newPath := filepath.Join("D:\\", fileName)
		// 新しいパスから新しいファイルを作成します
		newFile, err := os.Create(newPath)
		if err != nil {
			fmt.Printf("Failed to create new file: %v\n", err)
			continue
		}

		// 元のファイルを再度開きます
		file, err = os.Open(fileName)
		if err != nil {
			newFile.Close()
			fmt.Printf("Failed to open original file: %v\n", err)
			continue
		}

		// 元のファイルの内容を新しいファイルにコピーします
		_, err = io.Copy(newFile, file)
		if err != nil {
			fmt.Printf("Failed to copy file: %v\n", err)
		} else {
			fmt.Printf("Copied file to: %s\n", newPath)
		}

		// 全てのファイルを閉じます
		file.Close()
		newFile.Close()

		// 元のファイルを削除します
		err = os.Remove(fileName)
		if err != nil {
			fmt.Printf("Failed to remove original file: %v\n", err)
		}
	}
}

撮影したスクリーンショットをローカルの別のドライブ(D:\)に移動しています。これには、Go の標準パッケージである osio を使用します。
最後に、元のスクリーンショットファイルを削除しています。

3. プログラムの定期実行

このプログラムを定期的に実行することで、PC の監視を自動化することができます。Windows ではタスクスケジューラーを、macOS や Linux では cron を使って設定できます。

4. さらなる可能性

このコードはローカルの別のドライブにファイルを移動していますが、外部のネットワークドライブやクラウドストレージに移動すれば、遠隔からの監視も可能になります。ただし、セキュリティには十分注意してください。

取得したスクリーンショットから特定の文字を検出したり、画像の種類を検出したりすることで、より詳細な監視になります。目的にもよりますが、やり方は無数にありそうです。画像処理のライブラリを使用する場合は、Python を使いたくなりますね。

まとめ

以上、Go を使った PC 監視の自動化の一例でした。これがあなたの作業を少しでも楽にする一助となれば幸いです。

全体のコードは以下に置いてあります。
https://gist.github.com/KentaGoto/0ab51e680c516284813fe590793be826

Discussion